from django.conf import settings
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status, authentication, permissions
from rest_framework.authtoken.models import Token
from rest_framework.authtoken.views import ObtainAuthToken
from django.contrib.auth import authenticate
from .serializer import LoginSerializer
from user_app.serializer import UserSerializer
from django.utils.html import strip_tags
from django.core.mail import EmailMultiAlternatives
from django.template.loader import render_to_string
from user_app.models import CustomUser
from django.db.models import Q

class LoginView(APIView):
    serializer_class = LoginSerializer

    def post(self, request):
        serializer = self.serializer_class(data=request.data)
        
        if serializer.is_valid():
            email = serializer.validated_data['email']
            password = serializer.validated_data['password']
            user = authenticate(request, email=email, password=password)
            
            if user:
                if not user.is_active:
                    return Response({'error': 'Account is inactive, please check your mails'}, status=status.HTTP_403_FORBIDDEN)
                return self._create_token_response(user)
            return Response({'error': 'Unable to login with provided credentials.'}, status=status.HTTP_401_UNAUTHORIZED)
          
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

    def _create_token_response(self, user):
        token, created = Token.objects.get_or_create(user=user)
        return Response({'token': token.key}, status=status.HTTP_200_OK)
    
class LogoutView(APIView):
    authentication_classes = [authentication.TokenAuthentication]
    permission_classes = [permissions.IsAuthenticated]

    def post(self, request):
        try:
            request.user.auth_token.delete()
        except Token.DoesNotExist:
            return Response({'detail': 'Token not found.'}, status=status.HTTP_400_BAD_REQUEST)
        return Response({'detail': 'Successfully logged out.'}, status=status.HTTP_200_OK)
    
class RegisterView(APIView):
    def post(self, request):
        email = request.data.get('email')
        password = request.data.get('password')
        if CustomUser.objects.filter(email=email).exists():
            return Response({'error': 'A user with this email already exists.'}, status=status.HTTP_400_BAD_REQUEST)

        serialized = UserSerializer(data=request.data)
        if serialized.is_valid():
            user = serialized.save()  
            user.is_active = False
            user.set_password(password)
            user.save()
            self.send_email(user)
            return Response(serialized.data, status=status.HTTP_201_CREATED)
        else:
            return Response(serialized.errors, status=status.HTTP_400_BAD_REQUEST)

    def send_email(self, user):
        merge_data = {
            'name': user.username,
            'email': user.email,
            'token': user.verify_email_token
        }
        html_body = render_to_string("register_mail.html", merge_data)

        message = EmailMultiAlternatives(
            subject='Confirm your email',
            body=strip_tags(html_body),
            from_email=settings.DEFAULT_FROM_EMAIL,
            to=[user.email]
        )
        message.attach_alternative(html_body, "text/html")
        message.send(fail_silently=False)
        
class VerifyEmailView(APIView):
    def post(self, request):
        email = request.data.get('email')
        token = request.data.get('token')

        if not email or not token:
            return Response({"error": "Email and token are required."}, status=status.HTTP_400_BAD_REQUEST)

        user = CustomUser.objects.filter(Q(email=email) & Q(verify_email_token=token)).first()
        if user:
            if user.is_active:
                return Response({"error": "User has already been activated."}, status=status.HTTP_409_CONFLICT)
            
            user.is_active = True
            user.save()
            return Response(status=status.HTTP_200_OK)
        else:
            return Response({"error": "Invalid email or token."}, status=status.HTTP_400_BAD_REQUEST)

        
class ForgotPasswordView(APIView):
    def post(self, request):
        email = request.data.get('email')
        if not email:
            return Response({"error": "Email required."}, status=status.HTTP_400_BAD_REQUEST)
        
        try:
            user = CustomUser.objects.get(email=email)
            user.verify_email_token = CustomUser.generate_verification_token()
            user.save()
            self.send_email(user)
        except CustomUser.DoesNotExist:
            return Response({"error": "This email does not exist."}, status=status.HTTP_400_BAD_REQUEST)
        return Response(status=status.HTTP_200_OK)
    
    def send_email(self, user):
        merge_data = {
            'name': user.username,
            'email': user.email,
            'token': user.verify_email_token
        }
        html_body = render_to_string("forgot_password_mail.html", merge_data)

        message = EmailMultiAlternatives(
            subject='Reset your Password',
            body=strip_tags(html_body),
            from_email=settings.DEFAULT_FROM_EMAIL,
            to=[user.email]
        )
        message.attach_alternative(html_body, "text/html")
        message.send(fail_silently=False)

class ChangePasswordView(APIView):                
    def post(self, request):
        email = request.data.get('email')
        token = request.data.get('token')
        new_password = request.data.get('new_password')

        if not email or not token:
            return Response({"error": "Email and token are required."}, status=status.HTTP_400_BAD_REQUEST)

        user = CustomUser.objects.filter(Q(email=email) & Q(verify_email_token=token)).first()
        if user:
            user.set_password(new_password)
            user.save()
            return Response(status=status.HTTP_200_OK)
        else:
            return Response({"error": "Invalid email or token."}, status=status.HTTP_400_BAD_REQUEST)

class AuthView(ObtainAuthToken):
    authentication_classes = [authentication.TokenAuthentication]

    def get(self, request):
        if request.user.is_authenticated:
            return Response(request.user.id, status=status.HTTP_200_OK)
        return Response({"error": "User is not logged in"}, status=status.HTTP_401_UNAUTHORIZED)
    
    def post(self, request):
        email = request.data.get('email')
        if CustomUser.objects.filter(email=email).exists():
            return Response({'error': 'A user with this email already exists.'}, status=status.HTTP_400_BAD_REQUEST)
        return Response(status=status.HTTP_200_OK)