"""
Serializers — API REST v1
==========================
Serializadores para todos los endpoints del catálogo web.
"""

from datetime import date, datetime, timedelta

from django.conf import settings
from django.contrib.auth import get_user_model
from django.contrib.auth.password_validation import validate_password
from django.utils import timezone
from rest_framework import serializers

from apps.appointments.models import Cita, HorarioDoctora, Servicio
from apps.appointments.services import obtener_slots_disponibles, validar_disponibilidad
from apps.finance.models import Invoice, Payment
from apps.notifications.models import WhatsAppLog
from apps.ratings.models import PromedioGlobal, Valoracion

User = get_user_model()


# ============================================================
# AUTH / USUARIOS
# ============================================================
class RegisterSerializer(serializers.Serializer):
    """Registro de paciente nuevo."""

    email = serializers.EmailField()
    nombre = serializers.CharField(max_length=100)
    apellido = serializers.CharField(max_length=100)
    telefono = serializers.CharField(max_length=30, required=False, default="")
    password = serializers.CharField(write_only=True, min_length=8)
    password_confirm = serializers.CharField(write_only=True)

    def validate_email(self, value):
        if User.objects.filter(email__iexact=value).exists():
            raise serializers.ValidationError("Já existe uma conta com este email.")
        return value.lower()

    def validate(self, attrs):
        if attrs["password"] != attrs["password_confirm"]:
            raise serializers.ValidationError(
                {"password_confirm": "As senhas não coincidem."}
            )
        validate_password(attrs["password"])
        return attrs

    def create(self, validated_data):
        validated_data.pop("password_confirm")
        password = validated_data.pop("password")
        user = User.objects.create_user(
            password=password,
            rol="paciente",
            **validated_data,
        )
        return user


class ProfileSerializer(serializers.ModelSerializer):
    """Perfil del usuario autenticado."""

    full_name = serializers.CharField(source="get_full_name", read_only=True)

    class Meta:
        model = User
        fields = [
            "id", "email", "nombre", "apellido", "telefono",
            "foto_perfil", "rol", "is_verified", "fecha_registro",
            "full_name",
        ]
        read_only_fields = ["id", "email", "rol", "is_verified", "fecha_registro"]


class ProfileUpdateSerializer(serializers.ModelSerializer):
    """Actualización parcial del perfil."""

    class Meta:
        model = User
        fields = ["nombre", "apellido", "telefono", "foto_perfil"]

    def validate_foto_perfil(self, value):
        if value:
            if value.size > 5 * 1024 * 1024:
                raise serializers.ValidationError("Imagem muito grande (máx. 5 MB).")
            allowed = ("image/png", "image/jpeg", "image/gif", "image/webp")
            if value.content_type not in allowed:
                raise serializers.ValidationError("Apenas ficheiros de imagem são permitidos.")
        return value


class ChangePasswordSerializer(serializers.Serializer):
    """Cambio de contraseña del usuario autenticado."""

    old_password = serializers.CharField(write_only=True)
    new_password = serializers.CharField(write_only=True, min_length=8)

    def validate_old_password(self, value):
        user = self.context["request"].user
        if not user.check_password(value):
            raise serializers.ValidationError("Senha atual incorreta.")
        return value

    def validate_new_password(self, value):
        validate_password(value)
        return value


# ============================================================
# SERVICIOS
# ============================================================
class ServicioSerializer(serializers.ModelSerializer):
    class Meta:
        model = Servicio
        fields = [
            "id", "nombre", "descripcion", "duracion_minutos",
            "precio", "orden",
        ]
        read_only_fields = fields


# ============================================================
# CITAS
# ============================================================
class CitaListSerializer(serializers.ModelSerializer):
    """Serializer para listado de citas."""

    paciente_nombre = serializers.CharField(source="paciente.get_full_name", read_only=True)
    servicio_nombre = serializers.CharField(source="servicio.nombre", read_only=True)
    puede_cancelar = serializers.BooleanField(read_only=True)

    class Meta:
        model = Cita
        fields = [
            "id", "paciente", "paciente_nombre", "servicio",
            "servicio_nombre", "fecha_hora", "duracion_minutos",
            "estado", "notas_paciente", "notas_doctora",
            "puede_cancelar", "created_at",
        ]
        read_only_fields = [
            "id", "paciente", "duracion_minutos", "estado",
            "notas_doctora", "created_at",
        ]


class CitaCreateSerializer(serializers.Serializer):
    """Creación de nueva cita por paciente."""

    servicio = serializers.UUIDField()
    fecha_hora = serializers.DateTimeField()
    notas_paciente = serializers.CharField(max_length=500, required=False, default="")

    def validate_servicio(self, value):
        try:
            servicio = Servicio.objects.get(id=value, is_active=True)
        except Servicio.DoesNotExist:
            raise serializers.ValidationError("Serviço não encontrado.")
        return servicio

    def validate_fecha_hora(self, value):
        if settings.USE_TZ and timezone.is_naive(value):
            value = timezone.make_aware(value)
        if value <= timezone.now():
            raise serializers.ValidationError("Não é possível agendar no passado.")
        return value

    def validate(self, attrs):
        servicio = attrs["servicio"]
        fecha_hora = attrs["fecha_hora"]
        validar_disponibilidad(fecha_hora, servicio.duracion_minutos)
        return attrs

    def create(self, validated_data):
        from apps.appointments.services import crear_cita

        user = self.context["request"].user
        return crear_cita(
            paciente=user,
            servicio=validated_data["servicio"],
            fecha_hora=validated_data["fecha_hora"],
            notas=validated_data.get("notas_paciente", ""),
        )


class CitaCancelSerializer(serializers.Serializer):
    """Cancelación de cita por paciente."""

    motivo = serializers.CharField(max_length=500, required=False, default="")


class CitaEstadoSerializer(serializers.Serializer):
    """Cambio de estado por doctora/admin."""

    estado = serializers.ChoiceField(choices=Cita.Estado.choices)
    motivo = serializers.CharField(max_length=500, required=False, default="")


# ============================================================
# SLOTS DISPONIBLES
# ============================================================
class SlotQuerySerializer(serializers.Serializer):
    """Parámetros de consulta para slots disponibles."""

    date = serializers.DateField()
    service = serializers.UUIDField()

    def validate_date(self, value):
        if value < date.today():
            raise serializers.ValidationError("Não é possível consultar datas passadas.")
        return value

    def validate_service(self, value):
        if not Servicio.objects.filter(id=value, is_active=True).exists():
            raise serializers.ValidationError("Serviço não encontrado.")
        return value


class SlotSerializer(serializers.Serializer):
    """Representación de un slot disponible."""

    hora = serializers.CharField()
    datetime = serializers.CharField()


# ============================================================
# HORARIOS
# ============================================================
class HorarioDoctoraSerializer(serializers.ModelSerializer):
    dia_nombre = serializers.CharField(source="get_dia_semana_display", read_only=True)

    class Meta:
        model = HorarioDoctora
        fields = [
            "id", "dia_semana", "dia_nombre", "hora_inicio",
            "hora_fin", "activo",
        ]
        read_only_fields = fields


# ============================================================
# VALORACIONES
# ============================================================
class ValoracionListSerializer(serializers.ModelSerializer):
    """Listado de valoraciones (público: solo aprobadas)."""

    paciente_nombre = serializers.CharField(
        source="paciente.get_full_name", read_only=True
    )
    iniciales = serializers.CharField(source="iniciales_paciente", read_only=True)

    class Meta:
        model = Valoracion
        fields = [
            "id", "paciente_nombre", "iniciales", "estrellas",
            "comentario", "respuesta_doctora", "created_at",
        ]
        read_only_fields = fields


class ValoracionCreateSerializer(serializers.Serializer):
    """Creación de valoración por paciente."""

    cita = serializers.UUIDField()
    estrellas = serializers.IntegerField(min_value=1, max_value=5)
    comentario = serializers.CharField(max_length=500, required=False, default="")

    def validate_cita(self, value):
        user = self.context["request"].user
        try:
            cita = Cita.objects.get(
                id=value,
                paciente=user,
                estado=Cita.Estado.COMPLETADA,
                is_active=True,
            )
        except Cita.DoesNotExist:
            raise serializers.ValidationError(
                "Consulta não encontrada ou não concluída."
            )
        if Valoracion.objects.filter(cita=cita, is_active=True).exists():
            raise serializers.ValidationError("Já existe uma avaliação para esta consulta.")
        return cita

    def create(self, validated_data):
        user = self.context["request"].user
        return Valoracion.objects.create(
            paciente=user,
            cita=validated_data["cita"],
            estrellas=validated_data["estrellas"],
            comentario=validated_data.get("comentario", ""),
        )


class PromedioGlobalSerializer(serializers.ModelSerializer):
    class Meta:
        model = PromedioGlobal
        fields = [
            "promedio", "total", "estrellas_5", "estrellas_4",
            "estrellas_3", "estrellas_2", "estrellas_1",
        ]


# ============================================================
# FACTURAS
# ============================================================
class InvoiceListSerializer(serializers.ModelSerializer):
    """Listado de facturas."""

    paciente_nombre = serializers.CharField(
        source="paciente.get_full_name", read_only=True
    )
    servicio_nombre = serializers.CharField(
        source="servicio.nombre", read_only=True
    )
    saldo_pendiente = serializers.DecimalField(
        max_digits=14, decimal_places=2, read_only=True
    )

    class Meta:
        model = Invoice
        fields = [
            "id", "numero", "paciente_nombre", "servicio_nombre",
            "subtotal", "irt", "total", "estado", "metodo_pago",
            "saldo_pendiente", "fecha_emision", "created_at",
        ]
        read_only_fields = fields


class PaymentSerializer(serializers.ModelSerializer):
    class Meta:
        model = Payment
        fields = ["id", "monto", "metodo", "referencia", "created_at"]
        read_only_fields = fields


class InvoiceDetailSerializer(InvoiceListSerializer):
    """Detalle de factura con pagos."""

    pagos = PaymentSerializer(many=True, read_only=True)

    class Meta(InvoiceListSerializer.Meta):
        fields = InvoiceListSerializer.Meta.fields + ["notas", "pagos"]


# ============================================================
# NOTIFICACIONES (in-app via WhatsApp log)
# ============================================================
class NotificationSerializer(serializers.ModelSerializer):
    """Log de notificaciones WhatsApp del paciente."""

    class Meta:
        model = WhatsAppLog
        fields = [
            "id", "evento", "estado", "mensaje_error",
            "created_at",
        ]
        read_only_fields = fields
