"""
Modelos de Valoraciones — App Ratings
=======================================
Valoración de pacientes · Moderación · Promedio global.
"""

from django.conf import settings
from django.core.validators import MaxValueValidator, MinValueValidator
from django.db import models

from apps.core.models import BaseModel


class Valoracion(BaseModel):
    """Valoración de un paciente sobre una cita completada."""

    class Estado(models.TextChoices):
        PENDIENTE = "pendiente", "Pendente"
        APROBADA = "aprobada", "Aprovada"
        RECHAZADA = "rechazada", "Rejeitada"

    paciente = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        on_delete=models.CASCADE,
        related_name="valoraciones",
    )
    cita = models.OneToOneField(
        "appointments.Cita",
        on_delete=models.CASCADE,
        related_name="valoracion",
    )
    estrellas = models.PositiveSmallIntegerField(
        validators=[MinValueValidator(1), MaxValueValidator(5)],
    )
    comentario = models.CharField(max_length=500, blank=True, default="")
    estado = models.CharField(
        max_length=10,
        choices=Estado.choices,
        default=Estado.PENDIENTE,
    )
    respuesta_doctora = models.CharField(max_length=500, blank=True, default="")
    fecha_respuesta = models.DateTimeField(null=True, blank=True)

    class Meta:
        verbose_name = "Avaliação"
        verbose_name_plural = "Avaliações"
        ordering = ["-created_at"]

    def __str__(self):
        return f"{self.paciente.nombre} — {self.estrellas}★ — {self.get_estado_display()}"

    @property
    def puede_editar(self):
        """Editable solo dentro de las 48 horas posteriores a la creación."""
        from django.utils import timezone

        return (timezone.now() - self.created_at).total_seconds() < 48 * 3600

    @property
    def iniciales_paciente(self):
        n = self.paciente.nombre[:1].upper() if self.paciente.nombre else ""
        a = self.paciente.apellido[:1].upper() if self.paciente.apellido else ""
        return f"{n}{a}"


class PromedioGlobal(models.Model):
    """
    Singleton: almacena el promedio y distribución de valoraciones aprobadas.
    Actualizado por señal post_save de Valoracion.
    """

    promedio = models.DecimalField(max_digits=3, decimal_places=2, default=0)
    total = models.IntegerField(default=0)
    estrellas_5 = models.IntegerField(default=0)
    estrellas_4 = models.IntegerField(default=0)
    estrellas_3 = models.IntegerField(default=0)
    estrellas_2 = models.IntegerField(default=0)
    estrellas_1 = models.IntegerField(default=0)

    class Meta:
        verbose_name = "Média Global"
        verbose_name_plural = "Média Global"

    def __str__(self):
        return f"Promedio: {self.promedio}★ ({self.total} valoraciones)"

    @classmethod
    def get_instance(cls):
        obj, _ = cls.objects.get_or_create(pk=1)
        return obj

    def recalcular(self):
        """Recalcula desde las valoraciones aprobadas."""
        from django.db.models import Avg, Count, Q

        qs = Valoracion.objects.filter(estado=Valoracion.Estado.APROBADA, is_active=True)
        agg = qs.aggregate(
            promedio=Avg("estrellas"),
            total=Count("id"),
            e5=Count("id", filter=Q(estrellas=5)),
            e4=Count("id", filter=Q(estrellas=4)),
            e3=Count("id", filter=Q(estrellas=3)),
            e2=Count("id", filter=Q(estrellas=2)),
            e1=Count("id", filter=Q(estrellas=1)),
        )
        self.promedio = agg["promedio"] or 0
        self.total = agg["total"]
        self.estrellas_5 = agg["e5"]
        self.estrellas_4 = agg["e4"]
        self.estrellas_3 = agg["e3"]
        self.estrellas_2 = agg["e2"]
        self.estrellas_1 = agg["e1"]
        self.save()
