"""
Frontend HTML Views (not API)
Login, Register, etc.
"""
from django.shortcuts import render, redirect
from django.contrib.auth import authenticate, login, logout
from django.contrib import messages
from django.contrib.auth.decorators import login_required
from django.contrib.auth.tokens import default_token_generator
from django.utils.http import urlsafe_base64_encode, urlsafe_base64_decode
from django.utils.encoding import force_bytes, force_str
from django.core.mail import send_mail
from django.conf import settings
from accounts.models import User, VerificationCode, Wishlist
from django.contrib.auth.decorators import login_required
from django.views.decorators.cache import never_cache
from django.db.models import Sum
from notifications.models import NotificationPreference
from ai_features.models import AIConfiguration
from .captcha import generate_captcha, validate_captcha
from django.utils import timezone
import random
from orders.models import Order


def _send_verification_code(user, channel):
    """Helper to send verification code with rate limiting"""
    # Rate Limiting Logic: Max 5 codes in last 30 minutes
    time_threshold = timezone.now() - timezone.timedelta(minutes=30)
    recent_count = VerificationCode.objects.filter(
        user=user,
        channel=channel,
        created_at__gte=time_threshold
    ).count()

    if recent_count >= 5:
        return False, f"You have requested too many codes. Please try again after 30 minutes."

    code = f"{random.randint(100000, 999999)}"
    expiry = timezone.now() + timezone.timedelta(minutes=10)
    
    # Invalidate old codes
    VerificationCode.objects.filter(user=user, channel=channel, is_used=False).update(is_used=True)
    
    # Create new code
    VerificationCode.objects.create(
        user=user,
        channel=channel,
        code=code,
        contact_value=user.email if channel == 'email' else user.phone or '',
        expires_at=expiry,
        max_attempts=5
    )
    
    subj = 'Your Verification Code'
    body = f'Your {channel} verification code is: {code}. It expires in 10 minutes.'
    
    # Load configuration
    config = AIConfiguration.get_settings()
    
    sent = False
    if channel == 'email' and user.email:
        try:
            from_email = (config.email_from_address if config and config.email_from_address else getattr(settings, 'DEFAULT_FROM_EMAIL', 'no-reply@aibimagics.com'))
            send_mail(subj, body, from_email, [user.email], fail_silently=True)
            sent = True
        except Exception as e:
            print(f"Error sending email: {e}")
            sent = False
    elif channel == 'phone' and user.phone:
        try:
            # Prefer config from DB, fallback to settings
            sid = config.twilio_account_sid if config and config.twilio_account_sid else getattr(settings, 'TWILIO_ACCOUNT_SID', '')
            token = config.twilio_auth_token if config and config.twilio_auth_token else getattr(settings, 'TWILIO_AUTH_TOKEN', '')
            from_number = config.twilio_phone_number if config and config.twilio_phone_number else getattr(settings, 'TWILIO_PHONE_NUMBER', '')
            
            if sid and token and from_number:
                from twilio.rest import Client as TwilioClient
                client = TwilioClient(sid, token)
                client.messages.create(body=body, from_=from_number, to=user.phone)
                sent = True
        except Exception:
            pass
            
    return True, None

def _redirect_after_login(user):
    """Redirect user based on role"""
    try:
        # Check for Staff
        if hasattr(user, 'is_staff_member') and user.is_staff_member:
            return redirect('/staff/dashboard/')
            
        # Check for Vendor Role
        if user.role == 'VENDOR':
            # If profile exists, go to dashboard
            if hasattr(user, 'vendor_profile'):
                return redirect('/vendor/dashboard/')
            # If no profile but has role, go to registration to complete setup
            return redirect('vendor:register')

        return redirect('frontend:profile')
    except Exception as e:
        print(f"Error in redirect: {e}")
        return redirect('frontend:profile')


def register_view(request):
    """HTML Registration Page"""
    if request.method == 'POST':
        first_name = request.POST.get('first_name')
        last_name = request.POST.get('last_name')
        email = request.POST.get('email')
        phone = request.POST.get('phone')
        password = request.POST.get('password')
        confirm_password = request.POST.get('confirm_password')
        captcha_value = request.POST.get('captcha', '')
        if not validate_captcha(request, captcha_value):
            messages.error(request, 'Invalid captcha. Please try again.')
            code = generate_captcha(request)
            social_google_enabled = 'allauth.socialaccount.providers.google' in settings.INSTALLED_APPS
            social_facebook_enabled = 'allauth.socialaccount.providers.facebook' in settings.INSTALLED_APPS
            return render(request, 'auth/register.html', {
                'social_google_enabled': social_google_enabled,
                'social_facebook_enabled': social_facebook_enabled,
                'captcha_code': code,
            })
        # Validation
        if password != confirm_password:
            messages.error(request, 'Passwords do not match')
            code = generate_captcha(request)
            social_google_enabled = 'allauth.socialaccount.providers.google' in settings.INSTALLED_APPS
            social_facebook_enabled = 'allauth.socialaccount.providers.facebook' in settings.INSTALLED_APPS
            return render(request, 'auth/register.html', {
                'social_google_enabled': social_google_enabled,
                'social_facebook_enabled': social_facebook_enabled,
                'captcha_code': code,
            })
        
        if User.objects.filter(email=email).exists():
            messages.error(request, 'Email already registered')
            code = generate_captcha(request)
            social_google_enabled = 'allauth.socialaccount.providers.google' in settings.INSTALLED_APPS
            social_facebook_enabled = 'allauth.socialaccount.providers.facebook' in settings.INSTALLED_APPS
            return render(request, 'auth/register.html', {
                'social_google_enabled': social_google_enabled,
                'social_facebook_enabled': social_facebook_enabled,
                'captcha_code': code,
            })
        
        # Create user
        user = User.objects.create_user(
            email=email,
            password=password,
            first_name=first_name,
            last_name=last_name,
            phone=phone,
            role='CUSTOMER'
        )
        
        _send_verification_code(user, 'email')
        # We don't send phone code immediately on register anymore, wait until email verified
        # if user.phone:
        #    _send_verification_code(user, 'phone')
            
        request.session['pending_verification_user_id'] = user.id
        messages.success(request, 'Registration successful. Please verify your email.')
        return redirect('frontend:verify_email')
    
    social_google_enabled = 'allauth.socialaccount.providers.google' in settings.INSTALLED_APPS
    social_facebook_enabled = 'allauth.socialaccount.providers.facebook' in settings.INSTALLED_APPS
    code = generate_captcha(request)
    return render(request, 'auth/register.html', {
        'social_google_enabled': social_google_enabled,
        'social_facebook_enabled': social_facebook_enabled,
        'captcha_code': code,
    })


def login_view_html(request):
    """HTML Login Page"""
    if request.method == 'POST':
        email = request.POST.get('email')
        password = request.POST.get('password')
        captcha_value = request.POST.get('captcha', '')
        if not validate_captcha(request, captcha_value):
            messages.error(request, 'Invalid captcha. Please try again.')
            social_google_enabled = 'allauth.socialaccount.providers.google' in settings.INSTALLED_APPS
            social_facebook_enabled = 'allauth.socialaccount.providers.facebook' in settings.INSTALLED_APPS
            code = generate_captcha(request)
            return render(request, 'auth/login.html', {
                'social_google_enabled': social_google_enabled,
                'social_facebook_enabled': social_facebook_enabled,
                'captcha_code': code,
                'email': email,
            })
        
        # Django's authenticate expects 'username' even when using email
        user = authenticate(request, username=email, password=password)
        
        if user is not None:
            # Check verification status
            if not user.email_verified:
                request.session['pending_verification_user_id'] = user.id
                success, msg = _send_verification_code(user, 'email')
                if not success:
                    messages.error(request, msg)
                return redirect('frontend:verify_email')
                
            if not user.phone_verified:
                request.session['pending_verification_user_id'] = user.id
                if user.phone:
                    success, msg = _send_verification_code(user, 'phone')
                    if not success:
                        messages.error(request, msg)
                    return redirect('frontend:verify_phone')
                else:
                    return redirect('frontend:add_phone')
            
            # If everything verified
            login(request, user)
            VerificationCode.objects.filter(user=user).delete()
            messages.success(request, f'Welcome back, {user.first_name}!')
            return _redirect_after_login(user)
        else:
            messages.error(request, 'Invalid email or password')
            
    social_google_enabled = 'allauth.socialaccount.providers.google' in settings.INSTALLED_APPS
    social_facebook_enabled = 'allauth.socialaccount.providers.facebook' in settings.INSTALLED_APPS
    code = generate_captcha(request)
    return render(request, 'auth/login.html', {
        'social_google_enabled': social_google_enabled,
        'social_facebook_enabled': social_facebook_enabled,
        'captcha_code': code,
        'email': request.POST.get('email', ''),
    })


def verify_email_view(request):
    """View to verify email code"""
    user_id = request.session.get('pending_verification_user_id')
    if not user_id:
        messages.error(request, 'Session expired. Please login again.')
        return redirect('frontend:login')
    
    try:
        user = User.objects.get(pk=user_id)
    except User.DoesNotExist:
        messages.error(request, 'User not found.')
        return redirect('frontend:login')

    if request.method == 'POST':
        code = request.POST.get('code')
        vc = VerificationCode.objects.filter(user=user, channel='email', is_used=False).order_by('-created_at').first()
        
        if not vc or vc.is_expired():
            messages.error(request, 'Invalid or expired code.')
        elif vc.code != str(code).strip():
            vc.attempts += 1
            vc.save()
            messages.error(request, 'Invalid code.')
        else:
            vc.is_used = True
            vc.save()
            user.email_verified = True
            user.save()
            messages.success(request, 'Email verified successfully.')
            
            # Check if phone verification needed
            if not user.phone_verified:
                if user.phone:
                    success, msg = _send_verification_code(user, 'phone')
                    if not success:
                        messages.error(request, msg)
                    return redirect('frontend:verify_phone')
                else:
                    return redirect('frontend:add_phone')
            
            # All good
            user.is_verified = True
            user.save()
            
            # Clean up all verification codes for this user
            VerificationCode.objects.filter(user=user).delete()
            
            user.backend = 'django.contrib.auth.backends.ModelBackend'
            login(request, user)
            if 'pending_verification_user_id' in request.session:
                del request.session['pending_verification_user_id']
            return _redirect_after_login(user)
            
    return render(request, 'auth/verify_email.html', {'email': user.email})


def verify_phone_view(request):
    """View to verify phone code"""
    user_id = request.session.get('pending_verification_user_id')
    if not user_id:
        messages.error(request, 'Session expired. Please login again.')
        return redirect('frontend:login')
    
    try:
        user = User.objects.get(pk=user_id)
    except User.DoesNotExist:
        messages.error(request, 'User not found.')
        return redirect('frontend:login')
        
    if request.method == 'POST':
        code = request.POST.get('code')
        vc = VerificationCode.objects.filter(user=user, channel='phone', is_used=False).order_by('-created_at').first()
        
        if not vc or vc.is_expired():
            messages.error(request, 'Invalid or expired code.')
        elif vc.code != str(code).strip():
            vc.attempts += 1
            vc.save()
            messages.error(request, 'Invalid code.')
        else:
            vc.is_used = True
            vc.save()
            user.phone_verified = True
            user.is_verified = True
            user.save()
            messages.success(request, 'Congratulations you are successfully registered')
            
            user.backend = 'django.contrib.auth.backends.ModelBackend'
            login(request, user)
            VerificationCode.objects.filter(user=user).delete()
            
            if 'pending_verification_user_id' in request.session:
                del request.session['pending_verification_user_id']
            return _redirect_after_login(user)

    return render(request, 'auth/verify_phone.html', {'phone': user.phone})


def add_phone_view(request):
    """View to add phone if missing"""
    user_id = request.session.get('pending_verification_user_id')
    if not user_id:
        return redirect('frontend:login')
    
    try:
        user = User.objects.get(pk=user_id)
    except User.DoesNotExist:
        return redirect('frontend:login')

    if request.method == 'POST':
        phone = request.POST.get('phone')
        if phone:
            user.phone = phone
            user.save()
            success, msg = _send_verification_code(user, 'phone')
            if success:
                messages.success(request, 'Phone number saved. Verification code sent.')
            else:
                messages.error(request, msg)
            return redirect('frontend:verify_phone')
        else:
            messages.error(request, 'Please enter a valid phone number.')
            
    return render(request, 'auth/add_phone.html')


def resend_verification_view(request):
    """View to resend verification code"""
    user_id = request.session.get('pending_verification_user_id')
    if not user_id:
        return redirect('frontend:login')
    
    try:
        user = User.objects.get(pk=user_id)
    except User.DoesNotExist:
        return redirect('frontend:login')
        
    if request.method == 'POST':
        channel = request.POST.get('channel', 'email')
        
        # If trying to verify phone but no phone exists
        if channel == 'phone' and not user.phone:
            return redirect('frontend:add_phone')
            
        success, msg = _send_verification_code(user, channel)
        if success:
            messages.success(request, f'New code sent to your {channel}.')
        else:
            messages.error(request, msg)
            
        if channel == 'email':
            return redirect('frontend:verify_email')
        else:
            return redirect('frontend:verify_phone')
            
    return redirect('frontend:login')


def logout_view(request):
    """Logout view"""
    logout(request)
    messages.success(request, 'You have been logged out.')
    return redirect('frontend:login')


@login_required
def profile_view(request):
    """User Profile View"""
    # Force reload from DB to ensure role is fresh
    try:
        user = User.objects.get(pk=request.user.pk)
    except User.DoesNotExist:
        logout(request)
        return redirect('frontend:login')

    # Redirect vendors to dashboard
    if user.role == 'VENDOR':
        return _redirect_after_login(user)
        
    # Get stats
    recent_orders = Order.objects.filter(user=user).order_by('-created_at')[:5]
    total_orders = Order.objects.filter(user=user).count()
    wishlist_count = Wishlist.objects.filter(user=user).count()
    # reviews_count = user.reviews.count() if hasattr(user, 'reviews') else 0
    reviews_count = 0 
    
    # Calculate total spent
    total_spent = Order.objects.filter(user=user, is_paid=True).aggregate(Sum('total'))['total__sum'] or 0
        
    context = {
        'user': user,
        'recent_orders': recent_orders,
        'total_orders': total_orders,
        'wishlist_count': wishlist_count,
        'reviews_count': reviews_count,
        'total_spent': total_spent,
    }
    return render(request, 'auth/profile.html', context)


def forgot_password_view(request):
    """Forgot Password View"""
    if request.method == 'POST':
        email = request.POST.get('email')
        if not email:
            messages.error(request, 'Please enter your email address.')
            return render(request, 'auth/forgot_password.html')
            
        try:
            user = User.objects.get(email=email)
            
            # Generate token and link
            token = default_token_generator.make_token(user)
            uid = urlsafe_base64_encode(force_bytes(user.pk))
            
            # Construct absolute URL
            # Use request.build_absolute_uri to ensure full domain
            link = request.build_absolute_uri(
                f"/reset-password/{uid}/{token}/"
            )
            
            # Send email
            subject = "Reset your password - AiBiMagics"
            message = f"""Hello {user.first_name},

You requested to reset your password for your AiBiMagics account.
Please click the link below to set a new password:

{link}

If you did not request this, please ignore this email.
The link will expire in 24 hours.

Best regards,
AiBiMagics Team
"""
            from_email = getattr(settings, 'DEFAULT_FROM_EMAIL', 'no-reply@aibimagics.com')
            
            send_mail(subject, message, from_email, [email], fail_silently=False)
            
            messages.success(request, 'If an account exists with this email, you will receive a password reset link.')
        except User.DoesNotExist:
            # Don't reveal user existence
            messages.success(request, 'If an account exists with this email, you will receive a password reset link.')
        except Exception as e:
             messages.error(request, f'An error occurred while sending the email. Please try again later.')
             print(f"Error sending password reset email: {e}")
            
        return redirect('frontend:login')
        
    return render(request, 'auth/forgot_password.html')


def reset_password_view(request, uidb64, token):
    """Reset Password View"""
    try:
        uid = force_str(urlsafe_base64_decode(uidb64))
        user = User.objects.get(pk=uid)
    except (TypeError, ValueError, OverflowError, User.DoesNotExist):
        user = None

    if user is not None and default_token_generator.check_token(user, token):
        if request.method == 'POST':
            password = request.POST.get('password')
            confirm_password = request.POST.get('confirm_password')
            
            if password and confirm_password and password == confirm_password:
                user.set_password(password)
                user.save()
                messages.success(request, 'Your password has been reset successfully. You can now login.')
                return redirect('frontend:login')
            else:
                messages.error(request, 'Passwords do not match.')
        
        return render(request, 'auth/reset_password.html')
    else:
        messages.error(request, 'Password reset link is invalid or expired.')
        return redirect('frontend:login')


@login_required
def notification_settings_view(request):
    """Notification Settings View"""
    return render(request, 'auth/notifications.html')
