from django.conf import settings
from django.db import models

from utils.audit import AuditModel


def foto_muestra_upload_path(instance, filename):
    muestreo_id = instance.toma_muestra.muestreo_id if instance.toma_muestra_id else "unknown"
    toma_id = instance.toma_muestra_id or "unknown"
    tipo = (instance.tipo or "foto").strip().lower() or "foto"
    return f"muestreo_laboratorio/muestras/{muestreo_id}/{toma_id}/{tipo}_{filename}"


def foto_resultado_upload_path(instance, filename):
    muestreo_id = (
        instance.resultado_laboratorio.muestreo_id if instance.resultado_laboratorio_id else "unknown"
    )
    resultado_id = instance.resultado_laboratorio_id or "unknown"
    tipo = (instance.tipo or "foto").strip().lower() or "foto"
    return f"muestreo_laboratorio/resultados/{muestreo_id}/{resultado_id}/{tipo}_{filename}"


def informe_resultado_upload_path(instance, filename):
    muestreo_id = instance.muestreo_id or "unknown"
    return f"muestreo_laboratorio/informes/{muestreo_id}/{filename}"


class TomaMuestra(AuditModel):
    muestreo = models.OneToOneField(
        "recepciones.Muestreo",
        on_delete=models.CASCADE,
        related_name="toma_muestra",
    )

    fecha_toma = models.DateTimeField(null=True, blank=True)
    latitud = models.DecimalField(max_digits=9, decimal_places=6, null=True, blank=True)
    longitud = models.DecimalField(max_digits=9, decimal_places=6, null=True, blank=True)

    submuestras = models.JSONField(default=list, blank=True)
    observaciones = models.TextField(blank=True)


class FotoMuestra(models.Model):
    TIPO_CHOICES = [
        ("general", "General"),
        ("sello", "Sello"),
        ("muestra", "Muestra"),
        ("otro", "Otro"),
    ]

    toma_muestra = models.ForeignKey(TomaMuestra, on_delete=models.CASCADE, related_name="fotos")
    tipo = models.CharField(max_length=20, choices=TIPO_CHOICES, default="general")
    imagen = models.ImageField(upload_to=foto_muestra_upload_path)
    created_at = models.DateTimeField(auto_now_add=True)


class ResultadoLaboratorio(AuditModel):
    ESTADO_BORRADOR = "borrador"
    ESTADO_EN_CAPTURA = "en_captura"
    ESTADO_PUBLICADO = "publicado"

    ESTADO_CHOICES = [
        (ESTADO_BORRADOR, "Borrador"),
        (ESTADO_EN_CAPTURA, "En captura"),
        (ESTADO_PUBLICADO, "Publicado"),
    ]

    muestreo = models.OneToOneField(
        "recepciones.Muestreo",
        on_delete=models.CASCADE,
        related_name="resultado_laboratorio",
    )

    estado = models.CharField(max_length=20, choices=ESTADO_CHOICES, default=ESTADO_BORRADOR)

    informe = models.FileField(upload_to=informe_resultado_upload_path, null=True, blank=True)

    tags = models.JSONField(default=list, blank=True)
    alertas = models.JSONField(default=dict, blank=True)

    observaciones = models.TextField(blank=True)

    fecha_publicacion = models.DateTimeField(null=True, blank=True)
    publicado_por = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name="muestreo_laboratorio_resultados_publicados",
    )


class ParametroResultado(AuditModel):
    resultado_laboratorio = models.ForeignKey(
        ResultadoLaboratorio,
        on_delete=models.CASCADE,
        related_name="parametros",
    )
    parametro = models.ForeignKey(
        "catalogos.Parametro",
        on_delete=models.PROTECT,
        related_name="resultados_laboratorio",
    )

    valor = models.DecimalField(max_digits=10, decimal_places=3, null=True, blank=True)
    unidad = models.CharField(max_length=40, blank=True)
    observacion = models.TextField(blank=True)

    fuera_de_rango = models.BooleanField(default=False)

    class Meta:
        constraints = [
            models.UniqueConstraint(
                fields=["resultado_laboratorio", "parametro"],
                name="uq_parametro_por_resultado_laboratorio",
            )
        ]

    def save(self, *args, **kwargs):
        if not self.unidad and getattr(self.parametro, "unidad", None):
            self.unidad = self.parametro.unidad

        fuera = False
        if self.valor is not None and self.parametro_id:
            umbral_min = getattr(self.parametro, "umbral_min", None)
            umbral_max = getattr(self.parametro, "umbral_max", None)
            if umbral_min is not None and self.valor < umbral_min:
                fuera = True
            if umbral_max is not None and self.valor > umbral_max:
                fuera = True
        self.fuera_de_rango = fuera

        return super().save(*args, **kwargs)


class FotoResultado(models.Model):
    TIPO_CHOICES = [
        ("general", "General"),
        ("equipo", "Equipo"),
        ("muestra", "Muestra"),
        ("otro", "Otro"),
    ]

    resultado_laboratorio = models.ForeignKey(
        ResultadoLaboratorio,
        on_delete=models.CASCADE,
        related_name="fotos",
    )
    tipo = models.CharField(max_length=20, choices=TIPO_CHOICES, default="general")
    imagen = models.ImageField(upload_to=foto_resultado_upload_path)
    created_at = models.DateTimeField(auto_now_add=True)
