import logging
import threading

from django.views.decorators.http import require_POST
from django.views.decorators.csrf import csrf_exempt
from django.http import JsonResponse
from django.template.loader import render_to_string
from django.core.mail import send_mail
from django.conf import settings

from .forms import WaitlistForm, WaitlistVerificationForm, ResendVerificationForm
from .models import WaitlistEntry

logger = logging.getLogger(__name__)


@require_POST
@csrf_exempt
def submit_waitlist(request):
    """
    Step 1: Accept email, send verification code.
    """
    form = WaitlistForm(request.POST)

    if not form.is_valid():
        errors = form.errors.get('email')
        message = errors[0] if errors else 'Invalid request.'
        return JsonResponse({'status': 'error', 'message': message}, status=400)

    email = form.cleaned_data['email']
    entry, created = WaitlistEntry.objects.get_or_create(email=email)

    if entry.verified:
        return JsonResponse({
            'status': 'error',
            'message': 'This email is already on the waitlist.',
        }, status=400)

    code = entry.generate_verification_code()

    logger.info('Waitlist signup initiated', extra={'email': email, 'created': created})

    threading.Thread(
        target=_send_verification_email_safe,
        args=(email, code),
        daemon=True,
    ).start()

    return JsonResponse({
        'status': 'pending',
        'message': 'Check your inbox for a 6-digit verification code.',
        'email': email,
    })


@require_POST
@csrf_exempt
def verify_waitlist(request):
    """
    Step 2: Accept code, mark email as verified, send welcome email.
    """
    form = WaitlistVerificationForm(request.POST)

    if not form.is_valid():
        return JsonResponse({'status': 'error', 'errors': form.errors}, status=400)

    email = form.cleaned_data['email']
    code = form.cleaned_data['code']

    try:
        entry = WaitlistEntry.objects.get(email=email)
    except WaitlistEntry.DoesNotExist:
        return JsonResponse(
            {'status': 'error', 'message': 'Email not found. Please sign up first.'},
            status=404,
        )

    success, message = entry.verify_code(code)

    if not success:
        logger.warning(
            'Waitlist verification failed',
            extra={'email': email, 'reason': message},
        )
        return JsonResponse({'status': 'error', 'message': message}, status=400)

    logger.info('Waitlist email verified', extra={'email': email})

    threading.Thread(
        target=_send_welcome_email_safe,
        args=(email,),
        daemon=True,
    ).start()

    return JsonResponse({'status': 'success', 'message': 'You\'re on the list!'})


@require_POST
@csrf_exempt
def resend_verification(request):
    """
    Resend a fresh verification code to an unverified email.
    Rate limited at middleware level (3 per 5 min).
    """
    form = ResendVerificationForm(request.POST)

    if not form.is_valid():
        return JsonResponse({'status': 'error', 'errors': form.errors}, status=400)

    email = form.cleaned_data['email']

    try:
        entry = WaitlistEntry.objects.get(email=email)
    except WaitlistEntry.DoesNotExist:
        # Do not reveal whether the email exists — return neutral message
        return JsonResponse(
            {'status': 'success', 'message': 'If that email is registered, a new code has been sent.'},
        )

    if entry.verified:
        return JsonResponse(
            {'status': 'error', 'message': 'This email is already verified.'},
            status=400,
        )

    code = entry.generate_verification_code()

    logger.info('Verification code resent', extra={'email': email})

    threading.Thread(
        target=_send_verification_email_safe,
        args=(email, code),
        daemon=True,
    ).start()

    return JsonResponse(
        {'status': 'success', 'message': 'If that email is registered, a new code has been sent.'},
    )


# ---------------------------------------------------------------------------
# Internal email helpers — delegate to template files
# ---------------------------------------------------------------------------

def _send_verification_email(email: str, code: str) -> None:
    subject = 'Your Lifey verification code'
    body = render_to_string(
        'Emails/waitlist/email-verification.html',
        {'code': code},
    )
    send_mail(
        subject=subject,
        message='',
        html_message=body,
        from_email=settings.DEFAULT_FROM_EMAIL,
        recipient_list=[email],
        fail_silently=False,
    )


def _send_welcome_email(email: str) -> None:
    subject = 'You\'re on the Lifey waitlist 🎉'
    body = render_to_string('Emails/waitlist/email-welcome.html')
    send_mail(
        subject=subject,
        message='',
        html_message=body,
        from_email=settings.DEFAULT_FROM_EMAIL,
        recipient_list=[email],
        fail_silently=False,
    )


# ---------------------------------------------------------------------------
# Thread-safe wrappers — log failures instead of crashing silently
# ---------------------------------------------------------------------------

def _send_verification_email_safe(email: str, code: str) -> None:
    try:
        _send_verification_email(email, code)
    except Exception:
        logger.exception('Failed to send verification email', extra={'email': email})


def _send_welcome_email_safe(email: str) -> None:
    try:
        _send_welcome_email(email)
    except Exception:
        logger.exception('Failed to send welcome email', extra={'email': email})