from django.shortcuts import redirect, render

# from customer.models import Customer
# from emailconfig.views import send_email_using_config
from rest_framework import status, permissions
from rest_framework.response import Response
from rest_framework.views import APIView
from rest_framework.authtoken.models import Token
from django.contrib.auth import authenticate
from django.utils import timezone
from datetime import timedelta
import uuid
import logging
from users.models.users import (
    User,
    CustomRoleGroup,
    CustomPermission,
)  # Import CustomRoleGroup and CustomPermission
from package_details.models.package_details import PackageDetails
from user_ads_package.models.userpackage import UserPackage
from package_category.models.package_category import PackageCategory

# from employee.models import Employee # Import Employee model
from users.serializers.users_serializer import (
    GroupSerializer,
    PermissionSerializer,
    UserSerializer,
    LoginSerializer,
    RegistrationSerializer,
    PasswordResetRequestSerializer,
    PasswordResetConfirmSerializer,
    EmailVerificationSerializer,
    ResendVerificationSerializer,
    ResendPasswordResetSerializer,
    GroupWithPermissionsSerializer,  # Import the serializer that includes nested permissions
)
from drf_yasg.utils import swagger_auto_schema
from drf_yasg import openapi
from django.core.mail import send_mail, EmailMessage
from django.template.loader import render_to_string
from django.conf import settings
from users.utils.auth_utils import authenticate_user, get_user_by_credential

logger = logging.getLogger(__name__)


class LoginView(APIView):
    permission_classes = [permissions.AllowAny]

    @swagger_auto_schema(
        request_body=LoginSerializer,
    )
    def post(self, request):
        serializer = LoginSerializer(data=request.data)
        if serializer.is_valid():
            email = serializer.validated_data.get("email")
            user_id = serializer.validated_data.get("id")
            password = serializer.validated_data["password"]

            logger.debug(f"Login attempt for email: {email}, id: {user_id}")

            # Get user by credential
            user = get_user_by_credential(email=email, user_id=user_id)

            if not user:
                return Response(
                    {"error": "Either email or id must be provided."},
                    status=status.HTTP_400_BAD_REQUEST,
                )

            logger.debug(f"User found: {user.email}, is_active: {user.is_active}")

            # Verify password
            if not user.check_password(password):
                logger.debug("Password check failed")
                return Response(
                    {"error": "Invalid credentials"},
                    status=status.HTTP_401_UNAUTHORIZED,
                )

            # Authenticate and build response
            return authenticate_user(user, request)

        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)


class RegisterView(APIView):
    permission_classes = [permissions.AllowAny]

    @swagger_auto_schema(
        operation_description="Register a new user",
        request_body=RegistrationSerializer,
        responses={
            201: openapi.Response(
                description="User registered successfully",
                examples={
                    "application/json": {
                        "message": "User registered successfully. Please check your email to verify your account."
                    }
                },
            ),
            400: "Bad Request - Invalid data",
        },
    )
    def post(self, request):
        serializer = RegistrationSerializer(data=request.data)
        if serializer.is_valid():
            email = serializer.validated_data.get("email")
            try:
                # Check if user already exists
                existing_user = User.objects.get(email=email)

                # If user exists and is verified, don't allow re-registration
                if existing_user.email_verified:
                    return Response(
                        {
                            "error": "User with this email already exists and is verified. Please login instead."
                        },
                        status=status.HTTP_400_BAD_REQUEST,
                    )

                # If user exists but not verified, update their data and resend verification
                else:
                    # Update user data with new registration info
                    for attr, value in serializer.validated_data.items():
                        if attr != "password":
                            setattr(existing_user, attr, value)

                    # Update password if provided
                    if "password" in serializer.validated_data:
                        existing_user.set_password(
                            serializer.validated_data["password"]
                        )

                    existing_user.save()
                    user = existing_user
                    is_new_user = False

            except User.DoesNotExist:
                user = serializer.save()
                is_new_user = True

                # ==========================================
                # Logic: Assign Free Package Automatically (client only)
                # ==========================================
                if user.role == "client":
                    try:
                        # 1. Check if a Free Package exists (price is "0" or "Free")
                        free_package = PackageDetails.objects.filter(
                            price__in=["0", "Free", "free"]
                        ).first()

                        if not free_package:
                            # 2. If no Free Package exists, create a default one
                            # Note: Category is OneToOne, so we need a unique category for the free package
                            category_name = "Free Tier Category"
                            category, created = PackageCategory.objects.get_or_create(
                                name=category_name
                            )

                            # If category already has a package (due to OneToOne), create a new unique category
                            if not created and hasattr(category, "package_category"):
                                category = PackageCategory.objects.create(
                                    name=f"Free Tier {uuid.uuid4().hex[:6]}"
                                )

                            free_package = PackageDetails.objects.create(
                                category=category,
                                details="Default Free Membership Package",
                                price="0",  # Set price to 0
                                total_ads=5,  # Default: 5 Free Ads
                                space=10.0,  # Default: 10 MB Space
                                space_titanium="0",
                                support="Basic Support",
                                is_enterprise=False,
                            )
                            logger.info(f"Created new default Free Package: {free_package}")

                        # 3. Assign the package to the user without creating duplicates
                        user_package, created = UserPackage.objects.get_or_create(
                            user=user,
                            package=free_package,
                            defaults={
                                "total_ads": free_package.total_ads,
                                "total_space": free_package.space
                                if free_package.space
                                else 0,
                                "ads_posted": 0,
                                "used_space": 0,
                            },
                        )
                        if created:
                            logger.info(f"Assigned Free Package to user: {user.email}")
                        else:
                            logger.info(f"Free Package already assigned to user: {user.email}")

                    except Exception as e:
                        logger.error(
                            f"Failed to assign free package to user {user.email}: {str(e)}"
                        )
                # ==========================================

            # Generate verification token (6-digit OTP)
            token = user.create_verification_token()

            # Send verification email
            subject = "Verify Your discovercafe Account"

            # Plain text version
            text_message = f"""
            Hello {user.get_full_name() or user.email},

            Thank you for registering with discovercafe. To verify your account, please use the following verification code:

            {token}

            This code will expire in 5 minutes.

            If you did not register for an discovercafe account, please ignore this email.

            Best regards,
            The discovercafe Team
            """

            # HTML version
            html_message = render_to_string(
                "emails/verification_email.html",
                {"name": user.get_full_name() or user.email, "token": token},
            )

            try:
                print("Sending email to: ", user.email)
                send_mail(
                    subject=subject,
                    message=text_message,
                    from_email=settings.DEFAULT_FROM_EMAIL,
                    recipient_list=[user.email],
                    fail_silently=False,
                    html_message=html_message,
                )
                print("Email sent to: ", user.email)
                logger.info(f"Verification email sent to {user.email}")
            except Exception as e:
                logger.error(
                    f"Failed to send verification email to {user.email}: {str(e)}"
                )

            return Response(
                {
                    "message": f"User registered successfully. Please check your {user.email} to verify your account."
                },
                status=status.HTTP_201_CREATED,
            )
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)


class ResendVerificationView(APIView):
    permission_classes = [permissions.AllowAny]

    @swagger_auto_schema(
        request_body=ResendVerificationSerializer,
    )
    def post(self, request):
        serializer = ResendVerificationSerializer(data=request.data)
        if serializer.is_valid():
            email = serializer.validated_data["email"]

            try:
                user = User.objects.get(email=email)

                # Check if user is already verified
                if user.email_verified:
                    return Response(
                        {"error": "Email is already verified. Please login."},
                        status=status.HTTP_400_BAD_REQUEST,
                    )

                # Generate new verification token
                token = user.create_verification_token()

                # Send verification email
                subject = "Verify Your discovercafe Account"

                # Plain text version
                # Update the email content in RegisterView
                text_message = f"""
                Hello {user.get_full_name() or user.email},

                Welcome to discovercafe! Please verify your email address to complete your registration.

                Verification Code: {token}

                Or click this link to verify automatically:
                https://api.discovercafe.com/api/users/verify/?code={token}

                This code will expire in 5 minutes.

                Best regards,
                The discovercafe Team
                """

                # HTML version
                html_message = render_to_string(
                    "emails/verification_email.html",
                    {"name": user.get_full_name() or user.email, "token": token},
                )

                try:
                    send_mail(
                        subject=subject,
                        message="",
                        from_email=settings.DEFAULT_FROM_EMAIL,
                        recipient_list=[user.email],
                        fail_silently=False,
                        html_message=html_message,
                    )
                    logger.info(f"Verification email resent to {user.email}")
                except Exception as e:
                    logger.error(
                        f"Failed to resend verification email to {user.email}: {str(e)}"
                    )

                return Response(
                    {
                        "message": "Verification email has been resent. Please check your email."
                    }
                )
            except User.DoesNotExist:
                return Response(
                    {"error": "User not found."}, status=status.HTTP_404_NOT_FOUND
                )
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)


class VerifyEmailView(APIView):
    permission_classes = [permissions.AllowAny]

    @swagger_auto_schema(
        request_body=EmailVerificationSerializer,
    )
    def post(self, request):
        serializer = EmailVerificationSerializer(data=request.data)
        if serializer.is_valid():
            token = serializer.validated_data["token"]

            try:
                user = User.objects.get(verification_token=token)

                # Check if token is expired
                if user.verification_token_expires < timezone.now():
                    return Response(
                        {
                            "error": "Verification token has expired. Please request a new one."
                        },
                        status=status.HTTP_400_BAD_REQUEST,
                    )

                # Mark email as verified
                user.verify_email()

                return Response(
                    {"message": "Email verified successfully. You can now log in."}
                )
            except User.DoesNotExist:
                return Response(
                    {"error": "Invalid verification token."},
                    status=status.HTTP_400_BAD_REQUEST,
                )
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)


class AutoVerifyEmailView(APIView):
    permission_classes = [permissions.AllowAny]

    def get(self, request):
        code = request.query_params.get("code")

        if not code:
            return Response(
                {"error": "Verification code is required."},
                status=status.HTTP_400_BAD_REQUEST,
            )

        try:
            user = User.objects.get(verification_token=code)

            # Check if token is expired
            if user.verification_token_expires < timezone.now():
                return redirect(f"https://discovercafe.com/demo/login?verified=error")

            # Check if already verified
            if user.email_verified:
                # Redirect to frontend success page
                return redirect(f"https://discovercafe.com/demo")

            # Verify the user
            user.email_verified = True
            user.verification_token = None
            user.save()

            # Redirect to frontend success page
            return redirect(f"https://discovercafe.com/demo")

        except User.DoesNotExist:
            # Redirect to frontend error page
            return redirect(f"https://discovercafe.com/demo/login?verified=error")
        except Exception as e:
            return redirect(f"https://discovercafe.com/demo/login?verified=error")


class PasswordResetRequestView(APIView):
    permission_classes = [permissions.AllowAny]

    @swagger_auto_schema(request_body=PasswordResetRequestSerializer)
    def post(self, request):
        serializer = PasswordResetRequestSerializer(data=request.data)
        if serializer.is_valid():
            email = serializer.validated_data["email"]

            try:
                user = User.objects.get(email=email)
                if not user:
                    return Response(
                        {"error": "User not found."}, status=status.HTTP_404_NOT_FOUND
                    )

                # Generate reset token (6-digit OTP)
                token = user.create_reset_token()

                # Send reset email
                subject = "Reset Your discovercafe Password"

                # Plain text version
                text_message = f"""
                Hello {user.get_full_name() or user.email},

                We received a request to reset your discovercafe account password. To reset your password, please use the following code:

                {token}

                This code will expire in 1 hour.

                If you did not request a password reset, please ignore this email or contact support if you have concerns.

                Best regards,
                The discovercafe Team
                """

                # HTML version
                html_message = render_to_string(
                    "emails/password_reset_email.html",
                    {"name": user.get_full_name() or user.email, "token": token},
                )

                try:
                    send_mail(
                        subject=subject,
                        message=text_message,
                        from_email=settings.DEFAULT_FROM_EMAIL,
                        recipient_list=[user.email],
                        fail_silently=False,
                        html_message=html_message,
                    )
                    logger.info(f"Password reset email sent to {user.email}")
                except Exception as e:
                    logger.error(
                        f"Failed to send password reset email to {user.email}: {str(e)}"
                    )

                return Response(
                    {"message": "Password reset code has been sent to your email."}
                )
            except User.DoesNotExist:
                # For security reasons, don't reveal that the email doesn't exist
                logger.info(f"User Not Found: {email}")
                return Response(
                    {"message": "User Not Found"}, status=status.HTTP_404_NOT_FOUND
                )
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)


class PasswordResetConfirmView(APIView):
    permission_classes = [permissions.AllowAny]

    @swagger_auto_schema(
        request_body=PasswordResetConfirmSerializer,
    )
    def post(self, request):
        serializer = PasswordResetConfirmSerializer(data=request.data)
        if serializer.is_valid():
            token = serializer.validated_data["token"]
            password = serializer.validated_data["password"]

            try:
                user = User.objects.get(reset_token=token)

                # Check if token is expired
                if user.reset_token_expires < timezone.now():
                    return Response(
                        {
                            "error": "Password reset token has expired. Please request a new one."
                        },
                        status=status.HTTP_400_BAD_REQUEST,
                    )

                # Set new password
                user.reset_password(password)

                return Response(
                    {
                        "message": "Password has been reset successfully. You can now log in with your new password."
                    }
                )
            except User.DoesNotExist:
                return Response(
                    {"error": "Invalid password reset token."},
                    status=status.HTTP_400_BAD_REQUEST,
                )
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)


class AdminLoginView(APIView):
    permission_classes = [permissions.AllowAny]

    @swagger_auto_schema(
        request_body=LoginSerializer,
    )
    def post(self, request):
        serializer = LoginSerializer(data=request.data)
        if serializer.is_valid():
            email = serializer.validated_data.get("email")
            user_id = serializer.validated_data.get("id")
            password = serializer.validated_data["password"]

            try:
                if email:
                    user = User.objects.get(email=email)
                elif user_id:
                    user = User.objects.get(id=user_id)
                else:
                    return Response(
                        {"error": "Either email or id must be provided."},
                        status=status.HTTP_400_BAD_REQUEST,
                    )

                # Only allow admin role to get token
                if getattr(user, "role", None) != "admin":
                    return Response(
                        {
                            "error": "Only admin users are allowed to obtain access token."
                        },
                        status=status.HTTP_403_FORBIDDEN,
                    )

                if user.check_password(password):
                    token, created = Token.objects.get_or_create(user=user)
                    return Response(
                        {"token": token.key, "user": UserSerializer(user).data}
                    )
                else:
                    return Response(
                        {"error": "Invalid credentials"},
                        status=status.HTTP_401_UNAUTHORIZED,
                    )

            except User.DoesNotExist:
                return Response(
                    {"error": "Invalid credentials"},
                    status=status.HTTP_401_UNAUTHORIZED,
                )

        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
