from django.core.mail import send_mail
from django.conf import settings
from django.utils import timezone
from rest_framework import viewsets, status, generics
from rest_framework.decorators import action
from rest_framework.response import Response
from rest_framework.views import APIView
from rest_framework.permissions import IsAuthenticated, IsAdminUser, AllowAny
from rest_framework.parsers import MultiPartParser, FormParser

from .models import Registration, PaymentProof
from .serializers import (
    RegistrationSerializer, PublicRegistrationSerializer,
    PaymentProofSerializer, VerifyCodeSerializer, UpdateRegistrationStatusSerializer,
)
from apps.events.models import Event
from apps.events.serializers import EventListSerializer


class PublicEventListView(generics.ListAPIView):
    """Public endpoint: list events open for registration."""
    serializer_class = EventListSerializer
    permission_classes = [AllowAny]

    def get_queryset(self):
        return Event.objects.filter(
            is_active=True, is_archived=False, is_registerable=True
        ).order_by('start_date')


class PublicRegistrationView(APIView):
    """Public endpoint: register for an event."""
    permission_classes = [AllowAny]

    def post(self, request):
        serializer = PublicRegistrationSerializer(data=request.data)
        if serializer.is_valid():
            registration = serializer.save()
            self._send_confirmation_email(registration)
            return Response({
                'success': True,
                'registration_code': registration.registration_code,
                'message': 'Registration successful.',
                'data': PublicRegistrationSerializer(registration).data,
            }, status=status.HTTP_201_CREATED)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

    def _send_confirmation_email(self, registration):
        try:
            send_mail(
                subject=f'Registration Confirmed – {registration.event.name}',
                message=(
                    f'Dear {registration.full_name},\n\n'
                    f'Your registration for {registration.event.name} has been received.\n'
                    f'Your registration code is: {registration.registration_code}\n\n'
                    f'Please keep this code for reference.\n\nRegards,\nICTAZ'
                ),
                from_email=settings.DEFAULT_FROM_EMAIL,
                recipient_list=[registration.email],
                fail_silently=True,
            )
        except Exception:
            pass


class VerifyCodeView(APIView):
    """Public endpoint: verify a registration code."""
    permission_classes = [AllowAny]

    def post(self, request):
        serializer = VerifyCodeSerializer(data=request.data)
        if not serializer.is_valid():
            return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

        code = serializer.validated_data['registration_code'].strip()

        # Check registration module first
        try:
            reg = Registration.objects.select_related('event').get(registration_code=code)
            return Response({
                'found': True,
                'source': 'registration',
                'full_name': reg.full_name,
                'email': reg.email,
                'event_name': reg.event.name,
                'status': reg.status,
                'payment_status': reg.payment_status,
            })
        except Registration.DoesNotExist:
            pass

        # Check attendance module
        try:
            from apps.attendance.models import RegisteredMember
            member = RegisteredMember.objects.select_related('event').get(registration_code=code)
            return Response({
                'found': True,
                'source': 'attendance',
                'full_name': member.full_name,
                'email': member.email,
                'event_name': member.event.name if member.event else '',
                'status': member.status,
                'payment_status': member.payment_status,
            })
        except RegisteredMember.DoesNotExist:
            pass

        return Response({'found': False, 'message': 'Registration code not found.'})


class RegistrationViewSet(viewsets.ModelViewSet):
    """Admin endpoint: full CRUD for registrations."""
    serializer_class = RegistrationSerializer
    permission_classes = [IsAuthenticated]

    def get_queryset(self):
        qs = Registration.objects.select_related('event', 'payment_proof').all()
        event_id = self.request.query_params.get('event_id')
        status_filter = self.request.query_params.get('status')
        payment_status = self.request.query_params.get('payment_status')
        search = self.request.query_params.get('search')

        if event_id:
            qs = qs.filter(event_id=event_id)
        if status_filter:
            qs = qs.filter(status=status_filter)
        if payment_status:
            qs = qs.filter(payment_status=payment_status)
        if search:
            qs = qs.filter(full_name__icontains=search) | qs.filter(email__icontains=search) | qs.filter(registration_code__icontains=search)
        return qs

    def get_permissions(self):
        if self.action in ['list', 'retrieve']:
            return [IsAuthenticated()]
        return [IsAdminUser()]

    @action(detail=True, methods=['post'], permission_classes=[IsAdminUser])
    def update_status(self, request, pk=None):
        registration = self.get_object()
        serializer = UpdateRegistrationStatusSerializer(data=request.data)
        if not serializer.is_valid():
            return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
        if 'status' in serializer.validated_data:
            registration.status = serializer.validated_data['status']
        if 'payment_status' in serializer.validated_data:
            registration.payment_status = serializer.validated_data['payment_status']
        registration.save()
        return Response(RegistrationSerializer(registration).data)

    @action(detail=True, methods=['post'], permission_classes=[IsAdminUser],
            parser_classes=[MultiPartParser, FormParser])
    def upload_payment(self, request, pk=None):
        registration = self.get_object()
        file = request.FILES.get('file')
        if not file:
            return Response({'error': 'No file provided.'}, status=status.HTTP_400_BAD_REQUEST)
        proof, _ = PaymentProof.objects.update_or_create(
            registration=registration,
            defaults={'file': file, 'notes': request.data.get('notes', '')}
        )
        return Response(PaymentProofSerializer(proof).data, status=status.HTTP_201_CREATED)
