"""
Modelos — App Appointments (Citas)
====================================
Servicio · Horario de la doctora · Bloqueo de fechas · Cita · Log de cambios.
"""

from datetime import timedelta

from django.conf import settings
from django.core.exceptions import ValidationError
from django.db import models
from django.utils import timezone
from django.utils.translation import gettext_lazy as _

from apps.core.models import BaseModel


# ============================================================
# SERVICIO MEDICO
# ============================================================
class Servicio(BaseModel):
    """Servicios ofrecidos por la Dra. Mariela."""

    nombre = models.CharField(_("nome"), max_length=150)
    descripcion = models.TextField(_("descrição"), blank=True)
    icono_svg = models.TextField(
        _("icono SVG"),
        blank=True,
        help_text=_(
            "Código SVG do ícone (apenas o conteúdo &lt;path&gt; dentro do viewBox 0 0 24 24). "
            "Deixe vazio para usar um ícone por defeito."
        ),
    )
    foto = models.ImageField(
        _("foto do serviço"),
        upload_to="servicios/",
        blank=True,
        null=True,
        help_text=_("Imagem representativa do serviço. Será mostrada no cartão da página principal."),
    )

    class PosicionFoto(models.TextChoices):
        TOP = "top", _("Em cima")
        CENTER = "center", _("Centro")
        BOTTOM = "bottom", _("Em baixo")

    posicion_foto = models.CharField(
        _("posição da foto"),
        max_length=10,
        choices=PosicionFoto.choices,
        default=PosicionFoto.CENTER,
        help_text=_("Ajusta que parte da imagem se mostra no cartão."),
    )
    mostrar_en_home = models.BooleanField(
        _("mostrar no início"),
        default=True,
        help_text=_("Se estiver marcado, aparecerá na secção de serviços da página principal."),
    )
    duracion_minutos = models.PositiveIntegerField(
        _("duração (minutos)"),
        default=30,
        help_text=_("Duração do serviço em minutos."),
    )
    precio = models.DecimalField(
        _("precio"),
        max_digits=10,
        decimal_places=2,
        default=0,
    )
    orden = models.PositiveIntegerField(_("orden"), default=0)

    class Meta:
        verbose_name = _("serviço")
        verbose_name_plural = _("serviços")
        ordering = ["orden", "nombre"]

    def __str__(self):
        return f"{self.nombre} ({self.duracion_minutos} min)"


# ============================================================
# HORARIO DE LA DOCTORA
# ============================================================
class HorarioDoctora(BaseModel):
    """Horario semanal de la Dra. Mariela."""

    class DiaSemana(models.IntegerChoices):
        LUNES = 0, _("Segunda-feira")
        MARTES = 1, _("Terça-feira")
        MIERCOLES = 2, _("Quarta-feira")
        JUEVES = 3, _("Quinta-feira")
        VIERNES = 4, _("Sexta-feira")
        SABADO = 5, _("Sábado")
        DOMINGO = 6, _("Domingo")

    dia_semana = models.IntegerField(
        _("dia da semana"),
        choices=DiaSemana.choices,
    )
    hora_inicio = models.TimeField(_("hora início"))
    hora_fin = models.TimeField(_("hora fim"))
    activo = models.BooleanField(_("ativo"), default=True)

    class Meta:
        verbose_name = _("horário")
        verbose_name_plural = _("horários")
        ordering = ["dia_semana", "hora_inicio"]
        constraints = [
            models.UniqueConstraint(
                fields=["dia_semana", "hora_inicio", "hora_fin"],
                name="unique_horario_dia",
            ),
        ]

    def clean(self):
        if self.hora_inicio and self.hora_fin and self.hora_inicio >= self.hora_fin:
            raise ValidationError(_("A hora de início deve ser anterior à hora de fim."))

    def __str__(self):
        return f"{self.get_dia_semana_display()} {self.hora_inicio:%H:%M}-{self.hora_fin:%H:%M}"


# ============================================================
# BLOQUEO DE FECHAS
# ============================================================
class BloqueoFecha(BaseModel):
    """Dias bloqueados (vacaciones, festivos, etc.)."""

    fecha = models.DateField(_("data"), db_index=True)
    motivo = models.CharField(_("motivo"), max_length=200, blank=True)

    class Meta:
        verbose_name = _("bloqueio de data")
        verbose_name_plural = _("bloqueios de data")
        ordering = ["-fecha"]
        constraints = [
            models.UniqueConstraint(fields=["fecha"], name="unique_bloqueo_fecha"),
        ]

    def __str__(self):
        return f"{self.fecha} — {self.motivo or 'Bloqueado'}"


# ============================================================
# CITA MEDICA
# ============================================================
class Cita(BaseModel):
    """Cita medica con la Dra. Mariela."""

    class Estado(models.TextChoices):
        PENDIENTE = "pendiente", _("Pendente")
        CONFIRMADA = "confirmada", _("Confirmada")
        COMPLETADA = "completada", _("Concluída")
        CANCELADA = "cancelada", _("Cancelada")
        NO_ASISTIO = "no_asistio", _("Não Compareceu")

    paciente = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        on_delete=models.CASCADE,
        related_name="citas",
        verbose_name=_("paciente"),
    )
    servicio = models.ForeignKey(
        Servicio,
        on_delete=models.PROTECT,
        related_name="citas",
        verbose_name=_("serviço"),
    )
    fecha_hora = models.DateTimeField(_("data e hora"), db_index=True)
    duracion_minutos = models.PositiveIntegerField(_("duração (minutos)"))
    estado = models.CharField(
        _("estado"),
        max_length=20,
        choices=Estado.choices,
        default=Estado.PENDIENTE,
        db_index=True,
    )
    notas_paciente = models.TextField(_("notas do paciente"), blank=True)
    notas_doctora = models.TextField(_("notas da doutora"), blank=True)
    especialidad = models.CharField(
        _("especialidade"),
        max_length=200,
        blank=True,
        help_text=_("Sub-serviço/especialidade selecionado conforme o serviço pai."),
    )

    class Meta:
        verbose_name = _("consulta")
        verbose_name_plural = _("consultas")
        ordering = ["-fecha_hora"]
        indexes = [
            models.Index(fields=["fecha_hora", "estado"], name="idx_cita_fecha_estado"),
        ]

    def __str__(self):
        return (
            f"{self.paciente.get_full_name()} — "
            f"{self.servicio.nombre} — "
            f"{self.fecha_hora:%d/%m/%Y %H:%M}"
        )

    @property
    def fecha_hora_fin(self):
        return self.fecha_hora + timedelta(minutes=self.duracion_minutos)

    @property
    def puede_cancelar(self):
        """Paciente puede cancelar si faltan mas de 24h."""
        horas_anticipacion = getattr(settings, "CITA_CANCELACION_HORAS", 24)
        return (
            self.estado in (self.Estado.PENDIENTE, self.Estado.CONFIRMADA)
            and self.fecha_hora > timezone.now() + timedelta(hours=horas_anticipacion)
        )

    def save(self, *args, **kwargs):
        if not self.duracion_minutos:
            self.duracion_minutos = self.servicio.duracion_minutos
        super().save(*args, **kwargs)

    def clean(self):
        if self.fecha_hora and self.fecha_hora <= timezone.now():
            raise ValidationError(_("Não é possível agendar uma consulta no passado."))


# ============================================================
# LOG DE CAMBIOS DE CITA
# ============================================================
class CitaLog(models.Model):
    """Historial de cambios de estado de cada cita."""

    cita = models.ForeignKey(
        Cita,
        on_delete=models.CASCADE,
        related_name="logs",
        verbose_name=_("consulta"),
    )
    usuario = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        verbose_name=_("utilizador"),
    )
    estado_anterior = models.CharField(_("estado anterior"), max_length=20, blank=True)
    estado_nuevo = models.CharField(_("estado novo"), max_length=20)
    motivo = models.TextField(_("motivo"), blank=True)
    fecha = models.DateTimeField(_("data"), auto_now_add=True)

    class Meta:
        verbose_name = _("log de consulta")
        verbose_name_plural = _("logs de consultas")
        ordering = ["-fecha"]

    def __str__(self):
        return f"{self.cita_id} | {self.estado_anterior} -> {self.estado_nuevo} ({self.fecha:%d/%m %H:%M})"

