"""
Modelos base — Core
====================
Modelos abstractos y mixins reutilizables para todo el proyecto.
"""

import uuid

from django.db import models
from django.utils import timezone
from django.utils.translation import gettext_lazy as _


class TimeStampedModel(models.Model):
    """Mixin que agrega campos de auditoría created_at y updated_at."""

    created_at = models.DateTimeField(_("data de criação"), auto_now_add=True, db_index=True)
    updated_at = models.DateTimeField(_("data de atualização"), auto_now=True)

    class Meta:
        abstract = True
        ordering = ["-created_at"]


class UUIDModel(models.Model):
    """Mixin que usa UUID como clave primaria."""

    id = models.UUIDField(
        primary_key=True,
        default=uuid.uuid4,
        editable=False,
    )

    class Meta:
        abstract = True


class SoftDeleteModel(models.Model):
    """Mixin para borrado lógico (soft delete)."""

    is_active = models.BooleanField(_("ativo"), default=True, db_index=True)
    deleted_at = models.DateTimeField(_("data de eliminação"), null=True, blank=True)

    class Meta:
        abstract = True

    def soft_delete(self):
        from django.utils import timezone

        self.is_active = False
        self.deleted_at = timezone.now()
        self.save(update_fields=["is_active", "deleted_at", "updated_at"])

    def restore(self):
        self.is_active = True
        self.deleted_at = None
        self.save(update_fields=["is_active", "deleted_at", "updated_at"])


class BaseModel(UUIDModel, TimeStampedModel, SoftDeleteModel):
    """Modelo base completo: UUID + timestamps + soft delete."""

    class Meta(TimeStampedModel.Meta):
        abstract = True


class LoginAttempt(models.Model):
    """
    Registro de intentos de login fallidos para bloqueo de cuenta (OWASP A07).
    Se limpia automáticamente tras login exitoso.
    """

    username = models.CharField(_("utilizador"), max_length=150, db_index=True)
    ip_address = models.GenericIPAddressField(_("endereço IP"), db_index=True)
    user_agent = models.TextField(_("user agent"), blank=True, default="")
    attempted_at = models.DateTimeField(_("data da tentativa"), auto_now_add=True, db_index=True)
    was_successful = models.BooleanField(_("sucesso"), default=False)

    class Meta:
        verbose_name = _("tentativa de login")
        verbose_name_plural = _("tentativas de login")
        ordering = ["-attempted_at"]
        indexes = [
            models.Index(fields=["username", "attempted_at"]),
            models.Index(fields=["ip_address", "attempted_at"]),
        ]

    def __str__(self):
        status = "OK" if self.was_successful else "FAIL"
        return f"[{status}] {self.username} desde {self.ip_address} @ {self.attempted_at}"

    @classmethod
    def get_recent_failures(cls, username, minutes=None):
        """Obtiene intentos fallidos recientes para un usuario."""
        from django.conf import settings

        if minutes is None:
            minutes = getattr(settings, "ACCOUNT_LOGIN_LOCKOUT_MINUTES", 30)
        cutoff = timezone.now() - timezone.timedelta(minutes=minutes)
        return cls.objects.filter(
            username=username,
            was_successful=False,
            attempted_at__gte=cutoff,
        ).count()

    @classmethod
    def is_locked(cls, username):
        """Verifica si la cuenta está bloqueada por intentos fallidos."""
        from django.conf import settings

        max_attempts = getattr(settings, "ACCOUNT_LOGIN_MAX_ATTEMPTS", 5)
        return cls.get_recent_failures(username) >= max_attempts

    @classmethod
    def record_attempt(cls, username, ip_address, user_agent="", successful=False):
        """Registra un intento de login."""
        return cls.objects.create(
            username=username,
            ip_address=ip_address,
            user_agent=user_agent,
            was_successful=successful,
        )

    @classmethod
    def clear_failures(cls, username):
        """Limpia intentos fallidos tras login exitoso."""
        cls.objects.filter(username=username, was_successful=False).delete()

    @classmethod
    def cleanup_old_records(cls, days=90):
        """Elimina registros antiguos (para tarea Celery programada)."""
        cutoff = timezone.now() - timezone.timedelta(days=days)
        return cls.objects.filter(attempted_at__lt=cutoff).delete()


class SiteConfig(models.Model):
    """
    Configuración singleton del sitio — datos de la doctora y redes sociales.
    Solo puede existir un registro (se controla en admin).
    """

    # Identidad visual del sitio
    logo = models.ImageField(
        _("logotipo do site"), upload_to="site/logo/",
        blank=True, null=True,
        help_text=_("Logotipo principal do site (recomenda-se formato PNG com fundo transparente)"),
    )
    favicon = models.ImageField(
        _("\u00edcone do site (favicon)"), upload_to="site/favicon/",
        blank=True, null=True,
        help_text=_("\u00cdcone que aparece no separador do navegador (recomenda-se 32\u00d732 ou 180\u00d7180 px, PNG ou ICO)"),
    )

    # Textos del Hero / Banner
    titulo_hero_linea1 = models.CharField(
        _("título hero — linha 1"), max_length=100, blank=True, default="A Sua Saúde",
        help_text=_("Primeira linha do título principal do banner"),
    )
    titulo_hero_linea2 = models.CharField(
        _("título hero — linha 2"), max_length=100, blank=True, default="Feminina",
        help_text=_("Segunda linha do título principal do banner"),
    )
    titulo_hero_linea3 = models.CharField(
        _("título hero — linha destacada"), max_length=100, blank=True, default="É a Minha Prioridade",
        help_text=_("Linha destacada em cor rosa do título"),
    )
    subtitulo_hero = models.CharField(
        _("subtítulo hero"), max_length=300, blank=True,
        default="Acompanhamento profissional, humano e personalizado em cada etapa da sua vida.",
        help_text=_("Texto descritivo abaixo do título principal"),
    )

    # Datos personales
    nombre_completo = models.CharField(
        _("nome completo"), max_length=200,
        help_text=_("Nome completo da doutora, ex: Dra. Mariela Moreno Auti\u00e9"),
    )
    especialidad = models.CharField(
        _("especialidade"), max_length=200, blank=True, default="",
        help_text=_("Especialidade m\u00e9dica"),
    )
    foto_banner = models.ImageField(
        _("foto para banner"), upload_to="site/banner/",
        help_text=_("Imagem principal que se mostra no banner do site"),
    )
    foto_perfil = models.ImageField(
        _("foto de perfil"), upload_to="site/perfil/",
        blank=True, null=True,
        help_text=_("Foto de perfil (opcional, diferente do banner)"),
    )

    # Contacto
    telefono = models.CharField(
        _("telefone"), max_length=30,
        help_text=_("Número de telefone com código de país, ex: +244 923 456 789"),
    )
    email = models.EmailField(
        _("email"),
        help_text=_("Email de contacto público"),
    )
    direccion = models.TextField(
        _("endereço"), blank=True, default="",
        help_text=_("Endereço da consulta ou clínica principal"),
    )

    # Redes sociales (todas opcionales)
    facebook_url = models.URLField(_("Facebook"), blank=True, default="")
    instagram_url = models.URLField(_("Instagram"), blank=True, default="")
    twitter_url = models.URLField(_("Twitter / X"), blank=True, default="")
    linkedin_url = models.URLField(_("LinkedIn"), blank=True, default="")
    tiktok_url = models.URLField(_("TikTok"), blank=True, default="")
    youtube_url = models.URLField(_("YouTube"), blank=True, default="")
    whatsapp_url = models.URLField(
        _("WhatsApp (link directo)"), blank=True, default="",
        help_text=_("Ex: https://wa.me/244923456789"),
    )

    # ── Sección Sobre Mí ──
    sobre_mi_titulo = models.CharField(
        _("título secção Sobre Mim"), max_length=150, blank=True,
        default="Conheça a Dra. Mariela",
        help_text=_("Título principal da secção Sobre Mim"),
    )
    sobre_mi_texto = models.TextField(
        _("texto Sobre Mim"), blank=True,
        default="Com mais de uma década de experiência em ginecologia e obstetrícia, dedico-me a prestar cuidados médicos integrais, humanos e da mais alta qualidade.",
        help_text=_("Parágrafo descritivo da secção Sobre Mim"),
    )
    sobre_mi_texto2 = models.TextField(
        _("texto Sobre Mim (parágrafo 2)"), blank=True, default="",
        help_text=_("Segundo parágrafo opcional da secção Sobre Mim"),
    )
    sobre_mi_anios_experiencia = models.PositiveIntegerField(
        _("anos de experiência"), default=10,
        help_text=_("Número de anos de experiência profissional"),
    )
    sobre_mi_pacientes = models.CharField(
        _("pacientes atendidos"), max_length=20, blank=True, default="1,000+",
        help_text=_("Quantidade de pacientes atendidos (texto livre, ex: 1,000+)"),
    )
    sobre_mi_cirugias = models.CharField(
        _("cirurgias realizadas"), max_length=20, blank=True, default="500+",
        help_text=_("Quantidade de cirurgias realizadas (texto livre, ex: 500+)"),
    )

    # ── Horario ──
    horario_semana_label = models.CharField(
        _("etiqueta dias de semana"), max_length=50, blank=True, default="Segunda - Sexta",
    )
    horario_semana_horas = models.CharField(
        _("horas dias de semana"), max_length=30, blank=True, default="08:00 - 17:00",
    )
    horario_sabado_label = models.CharField(
        _("etiqueta sábado"), max_length=50, blank=True, default="Sábado",
    )
    horario_sabado_horas = models.CharField(
        _("horas sábado"), max_length=30, blank=True, default="08:00 - 12:00",
    )
    horario_domingo_label = models.CharField(
        _("etiqueta domingo"), max_length=50, blank=True, default="Domingo",
    )
    horario_domingo_horas = models.CharField(
        _("horas domingo"), max_length=30, blank=True, default="Fechado",
    )

    # ── Pie de Página ──
    texto_copyright = models.CharField(
        _("texto de copyright"), max_length=300, blank=True, default="",
        help_text=_("Texto do copyright no rodapé. Ex: © 2026 Dra. Mariela Moreno Autie - Ginecologia e Obstetrícia. Todos os direitos reservados."),
    )

    class Meta:
        verbose_name = _("configuração do site")
        verbose_name_plural = _("configuração do site")

    def __str__(self):
        return self.nombre_completo or "Configuração do site"

    def save(self, *args, **kwargs):
        # Forzar singleton: si ya existe un registro y no es este, impedir crear otro.
        if not self.pk and SiteConfig.objects.exists():
            raise ValueError("Solo puede existir un registro de SiteConfig.")
        super().save(*args, **kwargs)

    @classmethod
    def load(cls):
        """Retorna la instancia singleton o None si no se ha configurado."""
        return cls.objects.first()


class SobreMiCheck(models.Model):
    """Cada ítem check de la sección Sobre Mí, ilimitado y ordenable."""

    site_config = models.ForeignKey(
        SiteConfig,
        on_delete=models.CASCADE,
        related_name="sobre_mi_checks",
        verbose_name=_("configuración"),
    )
    texto = models.CharField(_("texto do check"), max_length=150)
    visible = models.BooleanField(_("visível"), default=True)
    orden = models.PositiveIntegerField(_("orden"), default=0)

    class Meta:
        verbose_name = _("check Sobre Mim")
        verbose_name_plural = _("checks Sobre Mim")
        ordering = ["orden"]

    def __str__(self):
        return self.texto


class HorarioSitio(models.Model):
    """Horario de atención configurable desde el admin."""

    site_config = models.ForeignKey(
        SiteConfig,
        on_delete=models.CASCADE,
        related_name="horarios",
        verbose_name=_("configuración"),
    )
    clinica = models.ForeignKey(
        "finance.Clinica",
        on_delete=models.CASCADE,
        related_name="horarios_sitio",
        verbose_name=_("clínica"),
        help_text=_("Selecione a clínica ou consultório"),
    )
    horario = models.CharField(
        _("horário"), max_length=150,
        help_text=_("Ex: Segunda - Sexta 08:00 - 17:00"),
    )
    visible = models.BooleanField(_("visível"), default=True)
    orden = models.PositiveIntegerField(_("orden"), default=0)

    class Meta:
        verbose_name = _("horário do site")
        verbose_name_plural = _("horários do site")
        ordering = ["orden"]

    def __str__(self):
        return f"{self.clinica.nombre} — {self.horario}"


class Galeria(BaseModel):
    """Álbum/galería que agrupa fotos y videos."""

    nombre = models.CharField(
        _("nome"), max_length=150,
        help_text=_("Nome da galeria, ex: Galeria 1, Clínica, etc."),
    )
    descripcion = models.TextField(
        _("descrição"), blank=True, default="",
        help_text=_("Descrição breve desta galeria (opcional)."),
    )
    mostrar_en_home = models.BooleanField(
        _("mostrar na home"), default=True, db_index=True,
        help_text=_("Se esta galeria se mostra na página principal"),
    )
    orden = models.PositiveIntegerField(_("orden"), default=0, db_index=True)

    class Meta:
        verbose_name = _("galeria")
        verbose_name_plural = _("galerias")
        ordering = ["orden", "-created_at"]

    def __str__(self):
        return self.nombre

    @property
    def total_items(self):
        return self.items.filter(is_active=True).count()


class GaleriaItem(BaseModel):
    """Foto o video dentro de una galería."""

    class TipoMedia(models.TextChoices):
        FOTO = "foto", _("Foto")
        VIDEO = "video", _("Vídeo")

    class PosicionFoto(models.TextChoices):
        TOP = "top", _("Em cima")
        CENTER = "center", _("Centro")
        BOTTOM = "bottom", _("Em baixo")

    galeria = models.ForeignKey(
        Galeria,
        on_delete=models.CASCADE,
        related_name="items",
        verbose_name=_("galeria"),
        null=True,
        blank=True,
    )
    titulo = models.CharField(
        _("título"), max_length=120, blank=True, default="",
        help_text=_("Título que aparece ao passar o cursor (opcional)"),
    )
    tipo = models.CharField(
        _("tipo"), max_length=5, choices=TipoMedia.choices, default=TipoMedia.FOTO,
    )
    imagen = models.ImageField(
        _("imagem"), upload_to="galeria/", blank=True, null=True,
        help_text=_("Foto ou miniatura do vídeo"),
    )
    video_url = models.URLField(
        _("URL do vídeo"), blank=True, default="",
        help_text=_("URL do YouTube ou vídeo externo (opcional)"),
    )
    video_file = models.FileField(
        _("ficheiro de vídeo"), upload_to="galeria/videos/", blank=True, null=True,
        help_text=_("Vídeo local (MP4, WebM). Tem prioridade sobre a URL externa."),
    )
    descripcion = models.CharField(
        _("descrição curta"), max_length=200, blank=True, default="",
    )
    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 (em cima, centro, em baixo)."),
    )
    mostrar_en_home = models.BooleanField(
        _("mostrar na home"), default=True, db_index=True,
        help_text=_("Se se mostra na secção galeria da página principal"),
    )
    orden = models.PositiveIntegerField(_("orden"), default=0, db_index=True)

    class Meta:
        verbose_name = _("elemento de galeria")
        verbose_name_plural = _("elementos de galeria")
        ordering = ["orden", "-created_at"]

    def __str__(self):
        return self.titulo or f"{self.get_tipo_display()} #{self.orden}"
