from django.shortcuts import render, redirect
from django.contrib.auth import authenticate, login
from django.contrib import messages

from .models import User, KnownDevice, LoginOTP
from .device_utils import (
    get_device_fingerprint, get_device_label,
    get_device_id_from_cookie, set_device_cookie,
)
from .email_utils import send_login_otp_email


# ------------------------------------------------------------------ #
# LOGIN — Step 1: Check credentials + device
# ------------------------------------------------------------------ #
def login_view(request):
    if request.method == 'POST':
        email    = request.POST.get('email', '').strip().lower()
        password = request.POST.get('password', '')

        user = authenticate(request, email=email, password=password)

        if not user:
            messages.error(request, 'Invalid email or password.')
            return render(request, 'accounts/login.html')

        # Generate device fingerprint from headers
        fingerprint = get_device_fingerprint(request)

        # Check cookie device ID (saved on previous trusted login)
        cookie_device_id = get_device_id_from_cookie(request)

        # Device is known if either fingerprint or cookie matches
        is_known = (
            KnownDevice.is_known(user, fingerprint) or
            (cookie_device_id and KnownDevice.is_known(user, cookie_device_id))
        )

        if is_known:
            # Known device — login directly
            login(request, user)
            device_label = get_device_label(request)
            KnownDevice.remember(
                user      = user,
                device_id = fingerprint,
                label     = device_label,
                ip        = request.META.get('REMOTE_ADDR', ''),
            )
            response = redirect('super_admin_dashboard' if user.is_super_admin else 'dashboard')
            set_device_cookie(response, fingerprint)
            return response

        else:
            # New device — send OTP
            otp_obj = LoginOTP.create(user=user, device_id=fingerprint)
            sent    = send_login_otp_email(
                email    = user.email,
                otp      = otp_obj.otp,
                name     = user.name,
                device   = get_device_label(request),
            )

            if not sent:
                messages.error(request, 'Failed to send OTP. Please try again.')
                return render(request, 'accounts/login.html')

            # Store user ID + device in session temporarily
            request.session['login_user_id']  = user.id
            request.session['login_device_id']= fingerprint

            return redirect('login_verify_otp')

    return render(request, 'accounts/login.html')


# ------------------------------------------------------------------ #
# LOGIN OTP — Step 2: Verify OTP, complete login
# ------------------------------------------------------------------ #
def login_verify_otp(request):
    user_id   = request.session.get('login_user_id')
    device_id = request.session.get('login_device_id')

    if not user_id or not device_id:
        messages.error(request, 'Session expired. Please login again.')
        return redirect('login')

    try:
        user = User.objects.get(id=user_id)
    except User.DoesNotExist:
        return redirect('login')

    if request.method == 'POST':
        action = request.POST.get('action', 'verify')

        # Resend OTP
        if action == 'resend':
            otp_obj = LoginOTP.create(user=user, device_id=device_id)
            send_login_otp_email(
                email  = user.email,
                otp    = otp_obj.otp,
                name   = user.name,
                device = get_device_label(request),
            )
            messages.success(request, 'A new OTP has been sent to your email.')
            return render(request, 'accounts/login_otp.html', {'email': user.email})

        # Verify OTP
        entered = request.POST.get('otp', '').strip()

        otp_obj = LoginOTP.objects.filter(
            user    = user,
            is_used = False,
        ).order_by('-created_at').first()

        if not otp_obj:
            messages.error(request, 'OTP not found. Please login again.')
            return redirect('login')

        if otp_obj.is_expired():
            messages.error(request, 'OTP expired. Please request a new one.')
            return render(request, 'accounts/login_otp.html', {'email': user.email})

        if otp_obj.otp != entered:
            messages.error(request, 'Incorrect OTP. Please try again.')
            return render(request, 'accounts/login_otp.html', {'email': user.email})

        # OTP valid — mark used
        otp_obj.is_used = True
        otp_obj.save()

        # Save as known device
        KnownDevice.remember(
            user      = user,
            device_id = device_id,
            label     = get_device_label(request),
            ip        = request.META.get('REMOTE_ADDR', ''),
        )

        # Clear session
        request.session.pop('login_user_id',   None)
        request.session.pop('login_device_id', None)

        # Login
        login(request, user)

        response = redirect('super_admin_dashboard' if user.is_super_admin else 'dashboard')
        set_device_cookie(response, device_id)
        return response

    return render(request, 'accounts/login_otp.html', {'email': user.email})
