import json
import uuid
from decimal import Decimal, InvalidOperation

import requests as http_req

from django.conf import settings
from django.http import JsonResponse
from django.shortcuts import render, redirect
from django.core.mail import send_mail
from django.contrib import messages
from django.urls import reverse
from django.utils import timezone
from django.views.decorators.csrf import csrf_exempt

from admissions.models import Program
from payments.models import Donation
from .models import Testimonial, GalleryImage


def index(request):
    testimonials = Testimonial.objects.filter(is_published=True).select_related('program')
    return render(request, 'website/index.html', {'testimonials': testimonials})


def about(request):
    return render(request, 'website/about.html')


def programs(request):
    all_programs = Program.objects.filter(is_active=True).order_by('level', 'name')
    return render(request, 'website/programs.html', {'programs': all_programs})


def contact(request):
    if request.method == 'POST':
        name = request.POST.get('name', '').strip()
        email = request.POST.get('email', '').strip()
        subject = request.POST.get('subject', '').strip()
        body = request.POST.get('message', '').strip()
        if name and email and subject and body:
            try:
                send_mail(
                    subject=f'[MLS Website] {subject}',
                    message=f'From: {name} <{email}>\n\n{body}',
                    from_email=None,
                    recipient_list=['info@mlsfoundationug.org'],
                    fail_silently=False,
                )
                messages.success(request, 'Thank you for reaching out! We will get back to you shortly.')
            except Exception as e:
                messages.error(request, f'Email could not be sent: {e}')
        else:
            messages.error(request, 'Please fill in all fields before submitting.')
        return redirect('website:contact')
    return render(request, 'website/contact.html')


def donate(request):
    return render(request, 'website/donate.html', {
        'flw_public_key': settings.FLW_PUBLIC_KEY,
    })


def donate_initiate(request):
    """AJAX: validate donor details, create pending Donation, return JSON for JS checkout."""
    if request.method != 'POST':
        return JsonResponse({'error': 'POST required.'}, status=405)

    name = request.POST.get('name', '').strip()
    email = request.POST.get('email', '').strip()
    phone = request.POST.get('phone', '').strip()
    amount_str = request.POST.get('amount', '').strip()
    message = request.POST.get('message', '').strip()

    if not name or not email:
        return JsonResponse({'error': 'Name and email are required.'}, status=400)

    try:
        amount = Decimal(amount_str)
        if amount < 1000:
            raise ValueError('Minimum donation is UGX 1,000')
    except (InvalidOperation, ValueError) as e:
        return JsonResponse({'error': str(e)}, status=400)

    tx_ref = f'MLS-DON-{uuid.uuid4().hex[:12].upper()}'
    Donation.objects.create(
        name=name, email=email, phone=phone,
        amount=amount, message=message,
        flw_tx_ref=tx_ref, status=Donation.PENDING,
    )

    return JsonResponse({
        'tx_ref': tx_ref,
        'public_key': settings.FLW_PUBLIC_KEY,
        'amount': float(amount),
        'customer': {'email': email, 'phone_number': phone, 'name': name},
        'description': 'Donation to Mirella & Lino Saputo Foundation LTD',
        'callback_url': request.build_absolute_uri(reverse('website:donation_callback')),
    })


@csrf_exempt
def donation_callback(request):
    """
    Handles Flutterwave redirect after a donation.

    Flutterwave sends data in two different formats depending on payment method:
      - Mobile money / USSD: ?resp={full JSON verification blob}
      - Card: ?status=successful&tx_ref=...&transaction_id=...
    """
    flw_verified = None  # will hold the already-verified response when present

    resp_raw = request.GET.get('resp', '')
    if resp_raw:
        # Mobile money path: Flutterwave embeds the full verification response
        # as a JSON string in the `resp` param (same structure as the v3 API response).
        try:
            flw_verified = json.loads(resp_raw)
            tx = flw_verified.get('data', {})
            status = tx.get('status', '')           # 'successful'
            tx_ref = tx.get('txRef', '')             # camelCase in this format
            transaction_id = str(tx.get('id', ''))
        except (ValueError, KeyError):
            status, tx_ref, transaction_id = '', '', ''
    else:
        # Card / standard path: separate query params
        status = request.GET.get('status', '')
        tx_ref = request.GET.get('tx_ref', '')
        transaction_id = request.GET.get('transaction_id', '')

    donation = Donation.objects.filter(flw_tx_ref=tx_ref).first()

    _SUCCESS_STATUSES = {'successful', 'success', 'completed'}

    if status.lower() not in _SUCCESS_STATUSES:
        if donation:
            donation.status = Donation.FAILED
            donation.save(update_fields=['status'])
        messages.error(request, 'Donation was not completed. Please try again.')
        return redirect('website:donate')

    # If the redirect didn't include pre-verified data, call the API ourselves.
    if flw_verified is None:
        try:
            api_resp = http_req.get(
                f'https://api.flutterwave.com/v3/transactions/{transaction_id}/verify',
                headers={'Authorization': f'Bearer {settings.FLW_SECRET_KEY}'},
                timeout=15,
            )
            flw_verified = api_resp.json()
        except Exception:
            messages.error(request, 'Could not verify donation. Please contact us with reference: ' + tx_ref)
            return redirect('website:donate')

    if flw_verified.get('status', '').lower() not in _SUCCESS_STATUSES:
        if donation:
            donation.status = Donation.FAILED
            donation.save(update_fields=['status'])
        messages.error(request, 'Donation verification failed. Contact us with reference: ' + tx_ref)
        return redirect('website:donate')

    if donation and donation.status != Donation.COMPLETED:
        donation.status = Donation.COMPLETED
        donation.flw_transaction_id = str(transaction_id)
        donation.completed_at = timezone.now()
        donation.save(update_fields=['status', 'flw_transaction_id', 'completed_at'])

    amount_display = f'{donation.amount:,.0f}' if donation else '?'
    messages.success(
        request,
        f'Thank you for your generous donation of UGX {amount_display}! '
        'Your support empowers youth and communities across Uganda.'
    )
    return redirect('website:donate')


def gallery(request):
    category = request.GET.get('category', '')
    images = GalleryImage.objects.filter(is_published=True)
    if category:
        images = images.filter(category=category)
    return render(request, 'website/gallery.html', {
        'images': images,
        'categories': GalleryImage.CATEGORY_CHOICES,
        'current_category': category,
    })


def portal_page(request):
    return render(request, 'website/portal.html')
