import random
import string
import hashlib
from django.shortcuts import render, redirect
from django.contrib.auth import login, logout
from django.contrib.auth.decorators import login_required
from django.contrib import messages
from django.core.mail import send_mail
from django.template.loader import render_to_string
from django.utils.html import strip_tags
from django.utils import timezone
from datetime import timedelta
from .models import User, LoginCode
from .forms import LoginForm, CodeForm

def generate_code():
    return ''.join(random.choices(string.digits, k=6))

def hash_code(code):
    return hashlib.sha256(code.encode()).hexdigest()

def login_view(request):
    if request.method == 'POST':
        form = LoginForm(request.POST)
        if form.is_valid():
            email = form.cleaned_data['email']
            try:
                user = User.objects.get(email=email)
            except User.DoesNotExist:
                messages.error(request, "No existe una cuenta con este correo.")
                return redirect('login')

            # Invalidate previous codes
            LoginCode.objects.filter(user=user, is_used=False).update(is_used=True)

            code = generate_code()
            expires_at = timezone.now() + timedelta(minutes=10)
            LoginCode.objects.create(
                user=user,
                code_hash=hash_code(code),
                expires_at=expires_at
            )

            # Send email with the OTP code
            try:
                html_message = render_to_string('emails/otp_code.html', {
                    'first_name': user.first_name or user.email,
                    'code': code,
                })
                plain_message = strip_tags(html_message)

                send_mail(
                    'Tu código de acceso a Citalis',
                    plain_message,
                    None,
                    [email],
                    html_message=html_message,
                    fail_silently=False,
                )
            except Exception:
                pass

            request.session['login_email'] = email
            return redirect('verify_code')
    else:
        form = LoginForm()
    return render(request, 'accounts/login.html', {'form': form})

def verify_code_view(request):
    email = request.session.get('login_email')
    if not email:
        return redirect('login')

    if request.method == 'POST':
        form = CodeForm(request.POST)
        if form.is_valid():
            code = form.cleaned_data['code']
            user = User.objects.get(email=email)
            login_code = LoginCode.objects.filter(
                user=user, 
                is_used=False,
                expires_at__gt=timezone.now()
            ).last()

            if login_code and login_code.code_hash == hash_code(code):
                login_code.is_used = True
                login_code.save()
                login(request, user)
                del request.session['login_email']
                return redirect('dashboard')
            else:
                if login_code:
                    login_code.attempts += 1
                    login_code.save()
                    if login_code.attempts >= 5:
                        login_code.is_used = True
                        login_code.save()
                        messages.error(request, "Demasiados intentos. Solicita un nuevo código.")
                        return redirect('login')
                messages.error(request, "Código inválido o expirado.")
    else:
        form = CodeForm()
    return render(request, 'accounts/verify_code.html', {'form': form})

def logout_view(request):
    logout(request)
    return redirect('login')


@login_required
def profile_view(request):
    return render(request, 'accounts/profile.html', {})
