import csv
import logging
import os
import platform

from django.contrib import messages
from django.contrib.auth.decorators import login_required
from django.core.mail import send_mail
from django.db import transaction
from django.db.models import Count, Q
from django.http import Http404, HttpResponse
from django.shortcuts import get_object_or_404, redirect, render
from django.utils import timezone

from .forms import EventSearchForm, OrganizerEventForm, RegistrationForm
from .models import Event, Registration

logger = logging.getLogger(__name__)


def _base_context(request):
    host_name = request.get_host().lower()
    agent_brand = 'AppWizzy' if host_name == 'appwizzy.com' else 'Flatlogic'
    now = timezone.now()
    return {
        'project_name': 'Northstar Events',
        'agent_brand': agent_brand,
        'django_version': __import__('django').get_version(),
        'python_version': platform.python_version(),
        'current_time': now,
        'host_name': host_name,
        'project_description': os.getenv('PROJECT_DESCRIPTION', 'Modern event publishing and registration for a single organizer team.'),
        'project_image_url': os.getenv('PROJECT_IMAGE_URL', ''),
    }


def home(request):
    now = timezone.now()
    search_form = EventSearchForm(request.GET or None)
    events = Event.objects.filter(is_published=True, end_at__gte=now).annotate(
        confirmed_registrations=Count('registrations', filter=Q(registrations__status=Registration.Status.CONFIRMED)),
        waitlist_registrations=Count('registrations', filter=Q(registrations__status=Registration.Status.WAITLIST)),
    )
    query = ''
    if search_form.is_valid():
        query = search_form.cleaned_data.get('q', '').strip()
        if query:
            events = events.filter(
                Q(title__icontains=query)
                | Q(summary__icontains=query)
                | Q(description__icontains=query)
                | Q(venue__icontains=query)
            )

    event_list = list(events)
    featured_event = event_list[0] if event_list else None
    stats = {
        'upcoming_events': Event.objects.filter(is_published=True, end_at__gte=now).count(),
        'confirmed_attendees': Registration.objects.filter(status=Registration.Status.CONFIRMED).count(),
        'waitlist_total': Registration.objects.filter(status=Registration.Status.WAITLIST).count(),
    }
    context = {
        **_base_context(request),
        'page_title': 'Northstar Events | Browse upcoming events and register online',
        'meta_description': 'Discover upcoming workshops, talks, and community events, then register in minutes with instant confirmation.',
        'search_form': search_form,
        'events': event_list,
        'featured_event': featured_event,
        'stats': stats,
        'query': query,
    }
    return render(request, 'core/index.html', context)


def event_detail(request, slug):
    event = get_object_or_404(
        Event.objects.annotate(
            confirmed_registrations=Count('registrations', filter=Q(registrations__status=Registration.Status.CONFIRMED)),
            waitlist_registrations=Count('registrations', filter=Q(registrations__status=Registration.Status.WAITLIST)),
        ),
        slug=slug,
        is_published=True,
    )
    form = RegistrationForm(request.POST or None, event=event)
    if request.method == 'POST':
        if not event.registration_is_open:
            form.add_error(None, 'Registration is not open for this event right now.')
        elif form.is_valid():
            with transaction.atomic():
                locked_event = Event.objects.select_for_update().get(pk=event.pk)
                if Registration.objects.filter(event=locked_event, email__iexact=form.cleaned_data['email']).exists():
                    form.add_error('email', 'This email is already registered for this event.')
                else:
                    registration = form.save(commit=False)
                    registration.event = locked_event
                    if locked_event.capacity and locked_event.confirmed_registrations_count >= locked_event.capacity:
                        registration.status = Registration.Status.WAITLIST
                    else:
                        registration.status = Registration.Status.CONFIRMED
                    registration.save()
                    email_sent = _send_registration_email(registration)
                    if email_sent:
                        messages.success(request, 'Registration saved and confirmation email sent.')
                    else:
                        messages.warning(request, 'Registration saved. Email delivery is not configured yet, so no confirmation email was sent.')
                    return redirect('registration_success', slug=locked_event.slug, registration_id=registration.pk)

    context = {
        **_base_context(request),
        'page_title': f'{event.title} | Register with Northstar Events',
        'meta_description': event.summary,
        'event': event,
        'form': form,
        'related_events': Event.objects.filter(is_published=True, end_at__gte=timezone.now()).exclude(pk=event.pk)[:3],
    }
    return render(request, 'core/event_detail.html', context)


def registration_success(request, slug, registration_id):
    registration = get_object_or_404(
        Registration.objects.select_related('event'),
        pk=registration_id,
        event__slug=slug,
    )
    context = {
        **_base_context(request),
        'page_title': f'Registration confirmed | {registration.event.title}',
        'meta_description': f'Confirmation details for {registration.event.title}.',
        'registration': registration,
        'event': registration.event,
    }
    return render(request, 'core/registration_success.html', context)


@login_required
def organizer_dashboard(request):
    now = timezone.now()
    events = Event.objects.annotate(
        confirmed_registrations=Count('registrations', filter=Q(registrations__status=Registration.Status.CONFIRMED)),
        waitlist_registrations=Count('registrations', filter=Q(registrations__status=Registration.Status.WAITLIST)),
        total_registrations=Count('registrations'),
    ).order_by('start_at')
    recent_registrations = Registration.objects.select_related('event').order_by('-created_at')[:8]
    context = {
        **_base_context(request),
        'page_title': 'Organizer dashboard | Northstar Events',
        'meta_description': 'Review upcoming events, attendee counts, and recent registrations for your organizer team.',
        'events': events,
        'recent_registrations': recent_registrations,
        'dashboard_stats': {
            'upcoming_events': events.filter(end_at__gte=now, is_published=True).count(),
            'confirmed_attendees': Registration.objects.filter(status=Registration.Status.CONFIRMED).count(),
            'waitlist_total': Registration.objects.filter(status=Registration.Status.WAITLIST).count(),
        },
    }
    return render(request, 'core/organizer_dashboard.html', context)


@login_required
def organizer_event_create(request):
    form = OrganizerEventForm(request.POST or None)
    if request.method == 'POST' and form.is_valid():
        event = form.save()
        messages.success(request, f'Event "{event.title}" created successfully.')
        return redirect('organizer_dashboard')

    context = {
        **_base_context(request),
        'page_title': 'Create event | Northstar Events',
        'meta_description': 'Create a new public event from the organizer dashboard.',
        'form': form,
        'form_mode': 'create',
        'form_title': 'Create a new event without opening Django Admin.',
        'form_intro': 'This custom organizer form covers the core publishing fields: schedule, venue, capacity, registration window, and public visibility.',
        'form_section_title': 'Fill in the event details.',
        'submit_label': 'Create event',
    }
    return render(request, 'core/organizer_event_form.html', context)


@login_required
def organizer_event_edit(request, slug):
    event = get_object_or_404(Event, slug=slug)
    form = OrganizerEventForm(request.POST or None, instance=event)
    if request.method == 'POST' and form.is_valid():
        updated_event = form.save()
        messages.success(request, f'Event "{updated_event.title}" updated successfully.')
        return redirect('organizer_dashboard')

    context = {
        **_base_context(request),
        'page_title': f'Edit {event.title} | Northstar Events',
        'meta_description': f'Update the event details for {event.title} from the organizer dashboard.',
        'form': form,
        'event': event,
        'form_mode': 'edit',
        'form_title': f'Edit “{event.title}” from the organizer dashboard.',
        'form_intro': 'Update the same publishing fields used during event creation, while keeping the public event URL stable.',
        'form_section_title': 'Update the event details.',
        'submit_label': 'Save changes',
    }
    return render(request, 'core/organizer_event_form.html', context)


@login_required
def export_attendees_csv(request, slug):
    event = get_object_or_404(Event, slug=slug)
    registrations = event.registrations.order_by('created_at')
    response = HttpResponse(content_type='text/csv')
    response['Content-Disposition'] = f'attachment; filename="{event.slug}-attendees.csv"'
    writer = csv.writer(response)
    writer.writerow(['Full name', 'Email', 'Company', 'Status', 'Registered at'])
    for registration in registrations:
        writer.writerow([
            registration.full_name,
            registration.email,
            registration.company,
            registration.get_status_display(),
            timezone.localtime(registration.created_at).strftime('%Y-%m-%d %H:%M'),
        ])
    return response



def _send_registration_email(registration):
    subject = f'Your registration for {registration.event.title}'
    if registration.status == Registration.Status.WAITLIST:
        intro = 'You have been added to the waitlist.'
    else:
        intro = 'Your spot is confirmed.'
    message = (
        f'Hi {registration.full_name},\n\n'
        f'{intro}\n\n'
        f'Event: {registration.event.title}\n'
        f'When: {timezone.localtime(registration.event.start_at).strftime("%B %d, %Y at %I:%M %p")}\n'
        f'Where: {registration.event.venue}\n\n'
        'We look forward to seeing you.\n'
        'Northstar Events'
    )
    try:
        send_mail(
            subject,
            message,
            os.getenv('DEFAULT_FROM_EMAIL', 'no-reply@example.com'),
            [registration.email],
            fail_silently=False,
        )
        return True
    except Exception as exc:
        logger.exception('Registration email failed for %s: %s', registration.email, exc)
        return False
