import io
import random
import string
import uuid
from django.core.files.base import ContentFile
from django.db import models
from django.utils import timezone
import qrcode

from campus.models import Enrollment


class DigitalSignature(models.Model):
    """
    Certificado digital criptográfico (.p12/.pfx) para firma digital PAdES de diplomas.
    """
    name = models.CharField(max_length=150, default="Certificado Institucional Lo Justo", verbose_name="Nombre Identificador")
    pfx_file = models.FileField(upload_to="certificates/signatures/", verbose_name="Archivo Certificado Digital (.p12 / .pfx)")
    p12_password = models.CharField(max_length=255, blank=True, verbose_name="Contraseña del Certificado")
    signer_name = models.CharField(max_length=200, default="Director Técnico & Calidad", verbose_name="Nombre del Firmante")
    signer_role = models.CharField(max_length=200, default="Supervisor de Laboratorio y Certificación", verbose_name="Cargo del Firmante")
    is_active = models.BooleanField(default=True, verbose_name="¿Firma Activa por Defecto?")
    created_at = models.DateTimeField(auto_now_add=True, verbose_name="Cargado el")

    class Meta:
        verbose_name = "Firma Digital (.p12/.pfx)"
        verbose_name_plural = "Firmas Digitales"
        ordering = ["-created_at"]

    def __str__(self):
        status = "ACTIVA" if self.is_active else "INACTIVA"
        return f"{self.name} ({self.signer_name}) - [{status}]"


class Certificate(models.Model):
    """
    Diploma oficial con código de autenticidad, firma digital criptográfica y QR de verificación.
    """
    uuid = models.UUIDField(default=uuid.uuid4, editable=False, unique=True, verbose_name="UUID Único")
    enrollment = models.OneToOneField(
        Enrollment,
        on_delete=models.CASCADE,
        related_name="certificate",
        verbose_name="Matrícula"
    )
    certificate_code = models.CharField(
        max_length=20,
        unique=True,
        blank=True,
        verbose_name="Código de Diploma (e.g. LJ-2026-A9B3)"
    )
    issued_at = models.DateTimeField(auto_now_add=True, verbose_name="Emitido el")
    pdf_file = models.FileField(
        upload_to="certificates/issued_pdfs/",
        blank=True,
        null=True,
        verbose_name="Archivo PDF Oficial Firmado"
    )
    sha256_hash = models.CharField(
        max_length=64,
        blank=True,
        verbose_name="Hash Criptográfico SHA-256"
    )
    is_digitally_signed = models.BooleanField(
        default=False,
        verbose_name="¿Firmado Criptográficamente (PAdES)?"
    )
    signer_name = models.CharField(
        max_length=200,
        blank=True,
        verbose_name="Firmante Autorizado"
    )
    qr_code_image = models.ImageField(
        upload_to="certificates/qrs/",
        blank=True,
        null=True,
        verbose_name="Imagen QR de Verificación"
    )

    class Meta:
        verbose_name = "Diploma / Certificado"
        verbose_name_plural = "Diplomas / Certificados"
        ordering = ["-issued_at"]

    def __str__(self):
        return f"Diploma {self.certificate_code} - {self.enrollment.user.username}"

    def save(self, *args, **kwargs):
        if not self.certificate_code:
            year = timezone.now().year
            rand_code = "".join(random.choices(string.ascii_uppercase + string.digits, k=6))
            self.certificate_code = f"LJ-{year}-{rand_code}"

        # Generate QR code image if not generated
        if not self.qr_code_image:
            qr_data = f"https://learning.lojustosac.com/validar-certificado/{self.certificate_code}/"
            qr = qrcode.QRCode(version=1, box_size=8, border=2)
            qr.add_data(qr_data)
            qr.make(fit=True)
            img = qr.make_image(fill_color="#044d29", back_color="white")
            
            buffer = io.BytesIO()
            img.save(buffer, format="PNG")
            file_name = f"qr_{self.certificate_code}.png"
            self.qr_code_image.save(file_name, ContentFile(buffer.getvalue()), save=False)

        super().save(*args, **kwargs)
