
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
from rest_framework.authtoken.models import Token
from django.contrib.auth import authenticate
from rest_framework.permissions import AllowAny, IsAuthenticated
from rest_framework.authentication import TokenAuthentication

from django.utils.http import urlsafe_base64_encode, urlsafe_base64_decode

from django.contrib.auth.tokens import default_token_generator

from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
from rest_framework.authtoken.models import Token
from django.contrib.auth import authenticate
from rest_framework.permissions import AllowAny, IsAuthenticated
from rest_framework.authentication import TokenAuthentication
from django.views.decorators.csrf import csrf_exempt

from django.core.mail import send_mail
from django.template.loader import render_to_string
from django.utils.html import strip_tags
from django.conf import settings
from django.contrib.auth import password_validation
from django.core.exceptions import ValidationError

from at_django_boilerplate.accounts.models import CustomUser


import logging
logger = logging.getLogger(__name__)


class LoginApiView(APIView):
    permission_classes = [AllowAny]  # This makes the endpoint open to all users

    def post(self, request, *args, **kwargs):
        # Get the username and password from the request data
        username = request.data.get('username')
        password = request.data.get('password')

        if not username or not password:
            return Response({"message": "Both username and password are required."}, status=status.HTTP_400_BAD_REQUEST)

        # Authenticate the user
        user = authenticate(username=username, password=password)
        if user is not None:
            # User is authenticated, generate token
            token, created = Token.objects.get_or_create(user=user)
            # You can retrieve the user's role or permission-based data here
            if user.is_superuser:
                role = "admin"
            elif user.get_manager():
                role = "manager"
            elif user.get_technician():
                role = "technician"
            else:
                role = "customer"
    
            return Response({
                "token": token.key,
                "role": role,
                "userId": user.id,
                "username": f"{user.first_name} {user.last_name}",
                "profile_photo": user.profile_photo.url if user.profile_photo.url else None,
                "message": "Login successful"
            }, status=status.HTTP_200_OK)
        
        # Invalid credentials
        return Response({"message": "Invalid username or password."}, status=status.HTTP_401_UNAUTHORIZED)
    

class ValidatePasswordAPIView(APIView):
    permission_classes = [IsAuthenticated]
    authentication_classes = [TokenAuthentication]
    def post(self, request):
        password = request.data.get('password')
        if not password:
            return Response({"success": False, "message": "Password is required."}, status=400)
        user = request.user
        if user.check_password(password):
            return Response({"success": True, "message": "Password is valid."}, status=200)
        return Response({"success": False, "message": "Password is incorrect."}, status=400)


class ResetPasswordAPIView(APIView):
    def post(self, request):
        # Get the email from the request data
        email = request.data.get('email')
        
        # Ensure the email is provided
        if not email:
            return Response({"success": False, "message": "Email address is required."}, status=400)

        try:
            # Check if the user exists in the database
            user = CustomUser.objects.get(email=email)
        except CustomUser.DoesNotExist:
            return Response({"success": False, "message": "User with this email does not exist."}, status=404)

        # Send the password reset email
        if self.send_reset_email(request, user, email):
            return Response({"success": True, "message": "Please check your email to reset your password."}, status=200)
        else:
            return Response({"success": False, "message": "Failed to send email. Please try again later."}, status=500)


    def send_reset_email(self, request, user, email):
        # Generate a password reset token
        token = default_token_generator.make_token(user)

        # Convert user.pk (integer) to string and then encode it to base64
        uid = urlsafe_base64_encode(str(user.pk).encode('utf-8'))  # Encode user ID to base64 string

        # Prepare the context for the email template
        context = {
            'user': user,
            'reset_link': f"http://localhost:3000/reset-password/{uid}/{token}/"  # Update the URL if needed (to your front-end)
        }

        # Render the HTML email template with the context
        html_message = render_to_string('email_template.html', context)

        # Subject of the email
        subject = "Password Reset Request"

        # Strip HTML tags for the plain-text version of the email
        message = strip_tags(html_message)

        # From email and recipient list
        from_email = settings.DEFAULT_FROM_EMAIL
        recipient_list = [email]

        try:
            # Send the email
            send_mail(subject, message, from_email, recipient_list, html_message=html_message)
            return True
        except Exception as e:
            print(f"Error sending email: {str(e)}")
            return False

class ResetPasswordConfirmAPIView(APIView):
    def get(self, request, uidb64, token):
        try:
            # Decode the user ID from base64
            uid = urlsafe_base64_decode(uidb64).decode('utf-8')
            user = CustomUser.objects.get(pk=uid)

            # Check if the token is valid
            if default_token_generator.check_token(user, token):
                return Response(
                    {"success": True, "message": "Token is valid."},
                    status=status.HTTP_200_OK
                )
            else:
                return Response(
                    {"success": False, "message": "Invalid or expired token."},
                    status=status.HTTP_400_BAD_REQUEST
                )

        except (TypeError, ValueError, OverflowError, CustomUser.DoesNotExist):
            return Response(
                {"success": False, "message": "Invalid or expired token."},
                status=status.HTTP_400_BAD_REQUEST
            )

    def post(self, request, uidb64, token):
        password = request.data.get('password')
        
        if not password:
            return Response(
                {"success": False, "message": "Password is required."},
                status=status.HTTP_400_BAD_REQUEST
            )

        try:
            # Decode the user ID from base64
            uid = urlsafe_base64_decode(uidb64).decode('utf-8')
            user = CustomUser.objects.get(pk=uid)
        except (TypeError, ValueError, OverflowError, CustomUser.DoesNotExist):
            return Response(
                {"success": False, "message": "Invalid user ID."},
                status=status.HTTP_400_BAD_REQUEST
            )

        try:
            password_validation.validate_password(password=password)
        except ValidationError as e:
            return Response(
                {"success": False, "message": str(e)},
                status=status.HTTP_400_BAD_REQUEST
            )
        # Validate the token
        if default_token_generator.check_token(user, token):
            # Set and save the new password
            user.set_password(password)
            user.save()
            return Response(
                {"success": True, "message": "Password has been reset successfully."},
                status=status.HTTP_200_OK
            )
        else:
            return Response(
                {"success": False, "message": "Invalid or expired token."},
                status=status.HTTP_400_BAD_REQUEST
            )

    
class UserProfileView(APIView):
    permission_classes = [IsAuthenticated]
    authentication_classes = [TokenAuthentication]

    def get(self, request):
        user = request.user 

        if user.is_superuser:
            print('Is Superuser')
            users = CustomUser.objects.all()
            data = [
                {
                    'id': u.id,
                    'email': u.email,
                    'first_name': u.first_name,
                    'last_name': u.last_name,
                }
                for u in users
            ]

        elif user.is_manager:  # Manager user only sees their own utility's data
            utility = user.get_utility()  # Get Utility
            users = utility.accounts_in_utility.all()

            data = [{
                'id': user.id,
                'email': user.email,
                'first_name': user.first_name,
                'last_name': user.last_name,
                'utility': str(utility)
            } 
            for u in users
            ] 

        elif user.is_technician: 
            utility = user.get_utility()  # Get Utility
            users = utility.accounts_in_utility.all()

            data = [{
                'id': u.id,
                'email': u.email,
                'first_name': u.first_name,
                'last_name': u.last_name,
                'utility': str(utility)
            } 
            for u in users if not u.is_manager and not u.is_superuser
            ]

        elif user.is_customer:  
            utility = user.get_utility()  # Get Utility
            data = [{
                'id': user.id,
                'email': user.email,
                'first_name': user.first_name,
                'last_name': user.last_name,
                'utility': str(utility)
            }]

        else:  
            data = None 

        return Response(data, status=status.HTTP_200_OK)
