"""
Views — API REST v1
=====================
Endpoints REST para el catálogo web de la Dra. Mariela.
"""

from django.contrib.auth import get_user_model
from django.utils import timezone
from drf_spectacular.utils import OpenApiParameter, extend_schema, extend_schema_view
from rest_framework import generics, status
from rest_framework.permissions import AllowAny, IsAuthenticated
from rest_framework.response import Response
from rest_framework.views import APIView
from rest_framework_simplejwt.views import TokenObtainPairView, TokenRefreshView

from apps.appointments.models import Cita, HorarioDoctora, Servicio
from apps.appointments.services import cambiar_estado_cita
from apps.finance.models import Invoice
from apps.notifications.models import WhatsAppLog
from apps.ratings.models import PromedioGlobal, Valoracion

from .permissions import EsDoctoraOAdmin, EsOwnerODoctoraOAdmin, EsPaciente
from .serializers import (
    ChangePasswordSerializer,
    CitaCancelSerializer,
    CitaCreateSerializer,
    CitaEstadoSerializer,
    CitaListSerializer,
    HorarioDoctoraSerializer,
    InvoiceDetailSerializer,
    InvoiceListSerializer,
    NotificationSerializer,
    ProfileSerializer,
    ProfileUpdateSerializer,
    PromedioGlobalSerializer,
    RegisterSerializer,
    ServicioSerializer,
    SlotQuerySerializer,
    SlotSerializer,
    ValoracionCreateSerializer,
    ValoracionListSerializer,
)

User = get_user_model()


# ============================================================
# AUTH
# ============================================================
@extend_schema(tags=["Auth"])
class LoginView(TokenObtainPairView):
    """POST /api/v1/auth/login/ — Obtener tokens JWT."""
    pass


@extend_schema(tags=["Auth"])
class RefreshView(TokenRefreshView):
    """POST /api/v1/auth/refresh/ — Renovar access token."""
    pass


@extend_schema(tags=["Auth"])
class RegisterView(generics.CreateAPIView):
    """POST /api/v1/auth/register/ — Registrar paciente nuevo."""

    serializer_class = RegisterSerializer
    permission_classes = [AllowAny]

    def create(self, request, *args, **kwargs):
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        user = serializer.save()
        return Response(
            {
                "id": str(user.id),
                "email": user.email,
                "nombre": user.nombre,
                "apellido": user.apellido,
                "message": "Conta criada com sucesso.",
            },
            status=status.HTTP_201_CREATED,
        )


# ============================================================
# PERFIL
# ============================================================
@extend_schema(tags=["Perfil"])
class ProfileView(APIView):
    """GET/PATCH /api/v1/profile/ — Perfil del usuario autenticado."""

    permission_classes = [IsAuthenticated]

    @extend_schema(responses=ProfileSerializer)
    def get(self, request):
        serializer = ProfileSerializer(request.user)
        return Response(serializer.data)

    @extend_schema(request=ProfileUpdateSerializer, responses=ProfileSerializer)
    def patch(self, request):
        serializer = ProfileUpdateSerializer(
            request.user, data=request.data, partial=True
        )
        serializer.is_valid(raise_exception=True)
        serializer.save()
        return Response(ProfileSerializer(request.user).data)


@extend_schema(tags=["Perfil"])
class ChangePasswordView(APIView):
    """POST /api/v1/profile/change-password/ — Cambiar contraseña."""

    permission_classes = [IsAuthenticated]

    @extend_schema(request=ChangePasswordSerializer)
    def post(self, request):
        serializer = ChangePasswordSerializer(
            data=request.data, context={"request": request}
        )
        serializer.is_valid(raise_exception=True)
        request.user.set_password(serializer.validated_data["new_password"])
        request.user.save(update_fields=["password"])
        return Response(
            {"message": "Senha atualizada com sucesso."},
            status=status.HTTP_200_OK,
        )


# ============================================================
# SERVICIOS
# ============================================================
@extend_schema(tags=["Servicios"])
class ServicioListView(generics.ListAPIView):
    """GET /api/v1/services/ — Servicios activos."""

    serializer_class = ServicioSerializer
    permission_classes = [AllowAny]
    queryset = Servicio.objects.filter(is_active=True).order_by("orden", "nombre")
    pagination_class = None


# ============================================================
# HORARIOS
# ============================================================
@extend_schema(tags=["Horarios"])
class HorarioListView(generics.ListAPIView):
    """GET /api/v1/schedule/ — Horarios de la doctora."""

    serializer_class = HorarioDoctoraSerializer
    permission_classes = [AllowAny]
    queryset = HorarioDoctora.objects.filter(activo=True, is_active=True).order_by(
        "dia_semana"
    )
    pagination_class = None


# ============================================================
# SLOTS DISPONIBLES
# ============================================================
@extend_schema(
    tags=["Citas"],
    parameters=[
        OpenApiParameter(name="date", type=str, description="Fecha (YYYY-MM-DD)"),
        OpenApiParameter(name="service", type=str, description="UUID del servicio"),
    ],
    responses=SlotSerializer(many=True),
)
class SlotListView(APIView):
    """GET /api/v1/slots/?date=YYYY-MM-DD&service=UUID — Slots disponibles."""

    permission_classes = [AllowAny]

    def get(self, request):
        query_serializer = SlotQuerySerializer(data=request.query_params)
        query_serializer.is_valid(raise_exception=True)

        fecha = query_serializer.validated_data["date"]
        servicio_id = query_serializer.validated_data["service"]
        servicio = Servicio.objects.get(id=servicio_id, is_active=True)

        from apps.appointments.services import obtener_slots_disponibles

        slots = obtener_slots_disponibles(fecha, servicio)
        return Response(slots)


# ============================================================
# CITAS
# ============================================================
@extend_schema_view(
    get=extend_schema(tags=["Citas"]),
    post=extend_schema(tags=["Citas"]),
)
class CitaListCreateView(APIView):
    """
    GET  /api/v1/appointments/ — Lista citas (filtradas por rol).
    POST /api/v1/appointments/ — Crear cita (solo pacientes).
    """

    permission_classes = [IsAuthenticated]

    def get(self, request):
        user = request.user
        if user.rol == "paciente":
            qs = Cita.objects.filter(paciente=user, is_active=True)
        else:
            qs = Cita.objects.filter(is_active=True)

        # Filtros opcionales
        estado = request.query_params.get("estado")
        if estado:
            qs = qs.filter(estado=estado)

        desde = request.query_params.get("desde")
        if desde:
            qs = qs.filter(fecha_hora__date__gte=desde)

        hasta = request.query_params.get("hasta")
        if hasta:
            qs = qs.filter(fecha_hora__date__lte=hasta)

        qs = qs.select_related("paciente", "servicio").order_by("-fecha_hora")

        # Paginación manual
        from rest_framework.pagination import PageNumberPagination

        paginator = PageNumberPagination()
        paginator.page_size = 20
        page = paginator.paginate_queryset(qs, request)
        serializer = CitaListSerializer(page, many=True)
        return paginator.get_paginated_response(serializer.data)

    def post(self, request):
        if request.user.rol != "paciente":
            return Response(
                {"detail": "Apenas os pacientes podem criar consultas."},
                status=status.HTTP_403_FORBIDDEN,
            )
        serializer = CitaCreateSerializer(
            data=request.data, context={"request": request}
        )
        serializer.is_valid(raise_exception=True)
        cita = serializer.save()
        return Response(
            CitaListSerializer(cita).data, status=status.HTTP_201_CREATED
        )


@extend_schema(tags=["Citas"])
class CitaDetailView(APIView):
    """
    GET   /api/v1/appointments/{id}/ — Detalle de cita.
    PATCH /api/v1/appointments/{id}/ — Cancelar (paciente) o cambiar estado (doctora).
    """

    permission_classes = [IsAuthenticated]

    def _get_cita(self, pk, user):
        try:
            cita = Cita.objects.select_related("paciente", "servicio").get(
                id=pk, is_active=True
            )
        except Cita.DoesNotExist:
            return None
        # Pacientes solo ven sus propias citas
        if user.rol == "paciente" and cita.paciente_id != user.id:
            return None
        return cita

    @extend_schema(responses=CitaListSerializer)
    def get(self, request, pk):
        cita = self._get_cita(pk, request.user)
        if not cita:
            return Response(
                {"detail": "Consulta não encontrada."},
                status=status.HTTP_404_NOT_FOUND,
            )
        return Response(CitaListSerializer(cita).data)

    def patch(self, request, pk):
        cita = self._get_cita(pk, request.user)
        if not cita:
            return Response(
                {"detail": "Consulta não encontrada."},
                status=status.HTTP_404_NOT_FOUND,
            )

        user = request.user

        # Paciente: solo puede cancelar
        if user.rol == "paciente":
            if not cita.puede_cancelar:
                return Response(
                    {"detail": "Não é possível cancelar com menos de 24h de antecedência."},
                    status=status.HTTP_400_BAD_REQUEST,
                )
            serializer = CitaCancelSerializer(data=request.data)
            serializer.is_valid(raise_exception=True)
            try:
                cambiar_estado_cita(
                    cita,
                    Cita.Estado.CANCELADA,
                    user,
                    serializer.validated_data.get("motivo", ""),
                )
            except Exception as e:
                return Response(
                    {"detail": str(e)}, status=status.HTTP_400_BAD_REQUEST
                )
            cita.refresh_from_db()
            return Response(CitaListSerializer(cita).data)

        # Doctora / Admin: cambio de estado general
        serializer = CitaEstadoSerializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        try:
            cambiar_estado_cita(
                cita,
                serializer.validated_data["estado"],
                user,
                serializer.validated_data.get("motivo", ""),
            )
        except Exception as e:
            return Response(
                {"detail": str(e)}, status=status.HTTP_400_BAD_REQUEST
            )
        cita.refresh_from_db()
        return Response(CitaListSerializer(cita).data)


# ============================================================
# VALORACIONES
# ============================================================
@extend_schema_view(
    get=extend_schema(tags=["Valoraciones"]),
    post=extend_schema(tags=["Valoraciones"]),
)
class ValoracionListCreateView(APIView):
    """
    GET  /api/v1/ratings/ — Valoraciones aprobadas (público).
    POST /api/v1/ratings/ — Crear valoración (paciente autenticado).
    """

    def get_permissions(self):
        if self.request.method == "GET":
            return [AllowAny()]
        return [IsAuthenticated()]

    def get(self, request):
        qs = (
            Valoracion.objects.filter(
                estado=Valoracion.Estado.APROBADA, is_active=True
            )
            .select_related("paciente")
            .order_by("-created_at")
        )

        from rest_framework.pagination import PageNumberPagination

        paginator = PageNumberPagination()
        paginator.page_size = 20
        page = paginator.paginate_queryset(qs, request)
        serializer = ValoracionListSerializer(page, many=True)
        return paginator.get_paginated_response(serializer.data)

    def post(self, request):
        if request.user.rol != "paciente":
            return Response(
                {"detail": "Apenas os pacientes podem criar avaliações."},
                status=status.HTTP_403_FORBIDDEN,
            )
        serializer = ValoracionCreateSerializer(
            data=request.data, context={"request": request}
        )
        serializer.is_valid(raise_exception=True)
        valoracion = serializer.save()
        return Response(
            ValoracionListSerializer(valoracion).data,
            status=status.HTTP_201_CREATED,
        )


@extend_schema(tags=["Valoraciones"])
class PromedioGlobalView(APIView):
    """GET /api/v1/ratings/summary/ — Promedio global de valoraciones."""

    permission_classes = [AllowAny]

    def get(self, request):
        stats = PromedioGlobal.get_instance()
        serializer = PromedioGlobalSerializer(stats)
        return Response(serializer.data)


# ============================================================
# FACTURAS
# ============================================================
@extend_schema(tags=["Finanzas"])
class InvoiceListView(APIView):
    """GET /api/v1/invoices/ — Facturas del usuario autenticado."""

    permission_classes = [IsAuthenticated]

    def get(self, request):
        user = request.user
        if user.rol == "paciente":
            qs = Invoice.objects.filter(paciente=user, is_active=True)
        else:
            qs = Invoice.objects.filter(is_active=True)

        estado = request.query_params.get("estado")
        if estado:
            qs = qs.filter(estado=estado)

        qs = qs.select_related("paciente", "servicio").order_by("-fecha_emision")

        from rest_framework.pagination import PageNumberPagination

        paginator = PageNumberPagination()
        paginator.page_size = 20
        page = paginator.paginate_queryset(qs, request)
        serializer = InvoiceListSerializer(page, many=True)
        return paginator.get_paginated_response(serializer.data)


@extend_schema(tags=["Finanzas"])
class InvoiceDetailView(APIView):
    """GET /api/v1/invoices/{id}/ — Detalle de factura con pagos."""

    permission_classes = [IsAuthenticated]

    def get(self, request, pk):
        try:
            invoice = Invoice.objects.select_related(
                "paciente", "servicio"
            ).prefetch_related("pagos").get(id=pk, is_active=True)
        except Invoice.DoesNotExist:
            return Response(
                {"detail": "Fatura não encontrada."},
                status=status.HTTP_404_NOT_FOUND,
            )
        # Pacientes solo ven sus propias facturas
        if request.user.rol == "paciente" and invoice.paciente_id != request.user.id:
            return Response(
                {"detail": "Fatura não encontrada."},
                status=status.HTTP_404_NOT_FOUND,
            )
        serializer = InvoiceDetailSerializer(invoice)
        return Response(serializer.data)


# ============================================================
# NOTIFICACIONES
# ============================================================
@extend_schema(tags=["Notificaciones"])
class NotificationListView(APIView):
    """GET /api/v1/notifications/ — Notificaciones del usuario."""

    permission_classes = [IsAuthenticated]

    def get(self, request):
        user = request.user
        if user.rol == "paciente":
            qs = WhatsAppLog.objects.filter(
                destinatario=user, is_active=True
            )
        else:
            qs = WhatsAppLog.objects.filter(is_active=True)

        qs = qs.order_by("-created_at")

        from rest_framework.pagination import PageNumberPagination

        paginator = PageNumberPagination()
        paginator.page_size = 20
        page = paginator.paginate_queryset(qs, request)
        serializer = NotificationSerializer(page, many=True)
        return paginator.get_paginated_response(serializer.data)
