from django.shortcuts import render
from django.views.decorators.csrf import csrf_exempt
from django.contrib.auth import authenticate
from django.utils.decorators import method_decorator
from django.core.exceptions import ObjectDoesNotExist
from django.conf import settings
from django.contrib.auth import get_user_model

from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.permissions import IsAuthenticated
from rest_framework.authtoken.models import Token
from rest_framework import status
from rest_framework.generics import UpdateAPIView

from .utils import is_valid_email
from .models import Device, LoginLog

from .serializers import ChangePasswordSerializer

CustomUser=get_user_model()

@method_decorator(csrf_exempt, name='dispatch')
class CustomAuthToken(APIView):
    permission_classes = []

    def post(self, request, *args, **kwargs):
        username = request.data.get('username')
        password = request.data.get('password')
        device_id = request.data.get('device_id')

        user = authenticate(username=username, password=password)

        if user is None and is_valid_email(username) == True:
            true_username = self.get_username_from_email(username)
            user = authenticate(username=true_username, password=password)

        if user:
            # user.device_id = device_id
            # user.save()
            # self.create_or_update_device(user, device_id)

            # token, created = Token.objects.get_or_create(user=user)
            # return Response({'token': token.key})

            if user.device_id is None or user.device_id == device_id or user.username == 'apple-test':
                user.device_id = device_id
                user.save()

                device_model = request.data.get('device_model')

                device = self.create_or_update_device(user, device_id, device_model)
                self.create_login_log(user, device)

                token, created = Token.objects.get_or_create(user=user)
                return Response({'token': token.key})
            else:
                return Response({'error': 'Vous ne pouvez pour l\'instant vous connecter sur plusieurs appareils en même temps. Veuillez vous déconnecter du précédent appareil. Autrement, veuillez contacter le support.'}, status=status.HTTP_403_FORBIDDEN)

        else:
            return Response({'error': 'L\'utilisateur et le mot de passe de correspondent pas'}, status=status.HTTP_401_UNAUTHORIZED)

    def create_or_update_device(self, user, device_id, device_model):
        obj, created = Device.objects.update_or_create(
                id=device_id,
                device_model=device_model,
                defaults={
                    'user': user
                }
            )
        return obj

    def create_login_log(self, user, device):
        LoginLog.objects.create(user=user, device=device)

    def get_username_from_email(self, email):
        try:
            user = CustomUser.objects.get(email=email)
            return user.username
        except ObjectDoesNotExist:
            return None

class Logout(APIView):
    permission_classes = (IsAuthenticated,)

    def post(self, request, *args, **kwargs):
        # request.user.auth_token.delete()

        device_id = request.data.get('device_id')
        if request.user.device_id == device_id:
            request.user.device_id = None
            request.user.save()

        Device.objects.filter(id=device_id).delete()

        return Response(status=status.HTTP_200_OK)

class ChangePasswordView(UpdateAPIView):
    serializer_class = ChangePasswordSerializer

    def update(self, request, *args, **kwargs):
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        user = serializer.save()
        # if using drf authtoken, create a new token
        if hasattr(user, 'auth_token'):
            user.auth_token.delete()
        token, created = Token.objects.get_or_create(user=user)
        # return new token
        return Response({'token': token.key}, status=status.HTTP_200_OK)
