# -*- coding: utf-8 -*-
"""
Adtlas Authentication Views

Enhanced authentication views for the Adtlas DAI Management System.
Includes login, registration, password reset, and profile management.

Features:
    - Enhanced login with remember me functionality
    - User registration with email verification
    - Password reset with secure tokens
    - Profile management
    - Activity logging and session management

Author: Adtlas Development Team
Version: 2.0.0
Last Updated: 2025-07-09
"""
 
from datetime import timedelta
from django.utils import timezone 
from django.db import transaction 
from django.contrib import messages
from django.http import JsonResponse 
from django.shortcuts import redirect
from django.views.generic import View, FormView
from django.contrib.auth.mixins import LoginRequiredMixin
from django.contrib.auth import login as auth_login, logout as auth_logout 

from apps.authentication.forms import (
    LoginForm, UserRegistrationForm, PasswordResetRequestForm,
    PasswordResetConfirmForm
)
from apps.accounts.models import (
    User, UserSession, UserActivity, 
    PasswordResetToken, Role, UserRole
)

from apps.common.utils import get_client_ip

class LoginView(FormView):
    """
    Enhanced login view with remember me functionality and security features.
    """
    template_name = "authentication/login.html"
    form_class = LoginForm
    
    def dispatch(self, request, *args, **kwargs):
        """
        Redirect authenticated users to dashboard.
        """
        if request.user.is_authenticated:
            return redirect("core:dashboard")
        return super().dispatch(request, *args, **kwargs)
    
    def get_form_kwargs(self):
        """
        Pass request to form for authentication.
        """
        kwargs = super().get_form_kwargs()
        kwargs["request"] = self.request
        return kwargs
    
    def form_valid(self, form):
        """
        Handle successful login.
        """
        user = form.get_user()
        
        # Log the user in
        auth_login(self.request, user)
        
        # Handle remember me functionality
        if form.cleaned_data.get("remember_me"):
            # Set session to expire in 30 days
            self.request.session.set_expiry(30 * 24 * 60 * 60)
        else:
            # Set session to expire when browser is closed
            self.request.session.set_expiry(0)
        
        # Update user last login and activity
        user.last_login = timezone.now()
        user.last_activity = timezone.now()
        user.save(update_fields=["last_login", "last_activity"])
        
        # Log user activity
        UserActivity.objects.create(
            user=user,
            action="login",
            ip_address=get_client_ip(self.request),
            user_agent=self.request.META.get("HTTP_USER_AGENT", ""),
            details={
                "remember_me": form.cleaned_data.get("remember_me", False),
                "login_method": "email_password"
            }
        )
        
        # Create or update user session
        UserSession.objects.update_or_create(
            user=user,
            session_key=self.request.session.session_key,
            defaults={
                "ip_address": get_client_ip(self.request),
                "user_agent": self.request.META.get("HTTP_USER_AGENT", ""),
                "last_activity": timezone.now(),
                "expires_at": timezone.now() + timedelta(days=30 if form.cleaned_data.get("remember_me") else 1),
                "is_active": True
            }
        )
        
        # Success message
        messages.success(
            self.request,
            f"Welcome back, {user.get_short_name()}!"
        )
        
        # Redirect to next URL or dashboard
        next_url = self.request.GET.get("next") or self.request.POST.get("next")
        if next_url:
            return redirect(next_url)
        return redirect("core:dashboard")
    
    def form_invalid(self, form):
        """
        Handle failed login attempt.
        """
        # Log failed login attempt
        email = form.cleaned_data.get("email")
        if email:
            # TODO: Log failed login attempts separately without requiring user_id
            # For now, we'll skip logging failed attempts to avoid IntegrityError
            pass
            # UserActivity.objects.create(
            #     user=None,
            #     action="login",
            #     ip_address=get_client_ip(self.request),
            #     user_agent=self.request.META.get("HTTP_USER_AGENT", ""),
            #     details={
            #         "email": email,
            #         "status": "failed",
            #         "error": "Invalid credentials"
            #     }
            # )
        
        return super().form_invalid(form)
    
 

 

class LogoutView(LoginRequiredMixin, View):
    """
    Enhanced logout view with session cleanup.
    """
    
    def get(self, request):
        """
        Handle logout request.
        """
        return self.post(request)
    
    def post(self, request):
        """
        Handle logout and cleanup.
        """
        user = request.user
        
        # Log user activity
        UserActivity.objects.create(
            user=user,
            action="logout",
            ip_address=get_client_ip(self.request),
            user_agent=request.META.get("HTTP_USER_AGENT", ""),
            details={"logout_method": "user_initiated"}
        )
        
        # Deactivate user session
        try:
            user_session = UserSession.objects.get(
                user=user,
                session_key=request.session.session_key,
                is_active=True
            )
            user_session.is_active = False
            user_session.save()
        except UserSession.DoesNotExist:
            pass
        
        # Logout user
        auth_logout(request)
        
        messages.success(request, "You have been successfully logged out.")
        return redirect("authentication:login")
    
 


class RegisterView(FormView):
    """
    User registration view with profile creation.
    """
    template_name = "authentication/register.html"
    form_class = UserRegistrationForm
    
    def dispatch(self, request, *args, **kwargs):
        """
        Redirect authenticated users to dashboard.
        """
        if request.user.is_authenticated:
            return redirect("core:dashboard")
        return super().dispatch(request, *args, **kwargs)
    
    def form_valid(self, form):
        """
        Handle successful registration.
        """
        with transaction.atomic():
            user = form.save()
            
            # Assign default role if available
            try:
                default_role = Role.objects.get(is_default=True, is_active=True)
                UserRole.objects.create(
                    user=user,
                    role=default_role,
                    assigned_by=None,  # System assignment
                    notes="Default role assigned during registration"
                )
            except Role.DoesNotExist:
                pass
            
            # Log user activity
            UserActivity.objects.create(
                user=user,
                action="create",
                object_type="User",
                object_id=str(user.id),
                object_repr=str(user),
                ip_address=get_client_ip(self.request),
                user_agent=self.request.META.get("HTTP_USER_AGENT", ""),
                details={
                    "registration_method": "email_form",
                    "email_verified": user.is_verified
                }
            )
        
        messages.success(
            self.request,
            "Account created successfully! Please check your email to verify your account."
        )
        
        # TODO: Send verification email
        
        return redirect("authentication:login")
    
 


class PasswordResetRequestView(FormView):
    """
    Password reset request view.
    """
    template_name = "authentication/password_reset_request.html"
    form_class = PasswordResetRequestForm
    
    def form_valid(self, form):
        """
        Handle password reset request.
        """
        reset_token = form.save()
        
        # Always show success message for security
        messages.success(
            self.request,
            "If the email address exists in our system, you will receive "
            "password reset instructions shortly."
        )
        
        # Log password reset request
        if reset_token:
            UserActivity.objects.create(
                user=reset_token.user,
                action="admin",
                object_type="PasswordResetToken",
                object_id=str(reset_token.id),
                object_repr=str(reset_token),
                ip_address=get_client_ip(self.request),
                user_agent=self.request.META.get("HTTP_USER_AGENT", ""),
                details={"action": "password_reset_requested"}
            )
        
        return redirect("authentication:login")
    
 


class PasswordResetConfirmView(FormView):
    """
    Password reset confirmation view.
    """
    template_name = "authentication/password_reset_confirm.html"
    form_class = PasswordResetConfirmForm
    
    def dispatch(self, request, *args, **kwargs):
        """
        Validate reset token before showing form.
        """
        self.token = kwargs.get("token")
        
        try:
            self.reset_token = PasswordResetToken.objects.get(
                token=self.token,
                is_used=False
            )
            
            if self.reset_token.is_expired():
                messages.error(request, "Password reset link has expired. Please request a new one.")
                return redirect("authentication:password_reset_request")
            
            self.user = self.reset_token.user
            
        except PasswordResetToken.DoesNotExist:
            messages.error(request, "Invalid password reset link. Please request a new one.")
            return redirect("authentication:password_reset_request")
        
        return super().dispatch(request, *args, **kwargs)
    
    def get_form_kwargs(self):
        """
        Pass user to form.
        """
        kwargs = super().get_form_kwargs()
        kwargs["user"] = self.user
        return kwargs
    
    def form_valid(self, form):
        """
        Handle successful password reset.
        """
        with transaction.atomic():
            # Save new password
            user = form.save()
            
            # Mark token as used
            self.reset_token.is_used = True
            self.reset_token.save()
            
            # Log password reset
            UserActivity.objects.create(
                user=user,
                action="update",
                object_type="User",
                object_id=str(user.id),
                object_repr=str(user),
                ip_address=get_client_ip(self.request),
                user_agent=self.request.META.get("HTTP_USER_AGENT", ""),
                details={"action": "password_reset_completed"}
            )
        
        messages.success(
            self.request,
            "Password reset successfully! Please log in with your new password."
        )
        
        return redirect("authentication:login")
    
 



# API Views for AJAX functionality
 
def check_email_availability(request):
    """
    Check if email is available for registration.
    """
    email = request.GET.get("email", "").lower().strip()
    
    if not email:
        return JsonResponse({"available": False, "error": "Email is required"})
    
    # Check if email exists
    exists = User.objects.filter(email=email).exists()
    
    return JsonResponse({
        "available": not exists,
        "email": email
    })
 