from django.db import models
from django.contrib.auth.models import User, Group
from django.db.models.signals import post_save
from django.dispatch import receiver
class Secretaria(models.Model):
    usuario = models.OneToOneField(User, on_delete=models.CASCADE, null=True, blank=True)  
    nui = models.CharField(max_length=15, unique=True, blank=True, null=True)  
    apellido = models.CharField(max_length=45, blank=True, null=True)
    nombre = models.CharField(max_length=45, blank=True, null=True)
    fecha_nacimiento = models.CharField(max_length=45, blank=True, null=True)
    nacionalidad = models.CharField(max_length=45, blank=True, null=True)
    provincia_nacimiento = models.CharField(max_length=45, blank=True, null=True)
    canto_nacimiento = models.CharField(max_length=45, blank=True, null=True)
    ciudad_nacimiento = models.CharField(max_length=45, blank=True, null=True)
    provincia_residencia = models.CharField(max_length=45, blank=True, null=True)
    canto_residencia = models.CharField(max_length=45, blank=True, null=True)
    ciudad_residencia = models.CharField(max_length=45, blank=True, null=True)
    direccion_residencia = models.CharField(max_length=100, blank=True, null=True)
    sexo = models.CharField(max_length=45, blank=True, null=True)
    genero = models.CharField(max_length=45, blank=True, null=True)
    tipo_sangre = models.CharField(max_length=45, blank=True, null=True)
    estado_civil = models.CharField(max_length=45, blank=True, null=True)
    etnia = models.CharField(max_length=45, blank=True, null=True)
    correo_personal = models.EmailField(blank=True, null=True)
    correo_institucional = models.EmailField(blank=True, null=True)
    telefono = models.CharField(max_length=20, blank=True, null=True) 
    celular = models.CharField(max_length=20, blank=True, null=True)  
    celular_emergencia = models.CharField(max_length=45, blank=True, null=True)
    nombre_emergencia = models.CharField(max_length=45, blank=True, null=True)
    discapacidad = models.CharField(max_length=45, blank=True, null=True)

    def __str__(self):
        return f"Secretaria: {self.nombre} {self.apellido}"

@receiver(post_save, sender=Secretaria)
def crear_usuario_secretaria(sender, instance, created, **kwargs):
    if created and instance.usuario is None:
        username = str(instance.nui)  # aseguramos string
        user = User.objects.create_user(
            username=username,
            email=instance.correo_institucional,
            password='Alu_user8*',
            first_name=instance.nombre,
            last_name=instance.apellido,
        )
        group, _ = Group.objects.get_or_create(name='Secretaria')
        user.groups.add(group)

        # actualizamos solo el campo 'usuario' sin llamar a save()
        Secretaria.objects.filter(pk=instance.pk).update(usuario=user)

class Estudiante(models.Model):
    usuario = models.OneToOneField(User, on_delete=models.CASCADE, null=True, blank=True)  
    nui = models.IntegerField(unique=True, null=False, blank=False) 
    apellido = models.CharField(max_length=45, blank=True, null=True)
    nombre = models.CharField(max_length=45, blank=True, null=True)
    fecha_nacimiento = models.CharField(max_length=45, blank=True, null=True)
    nacionalidad = models.CharField(max_length=45, blank=True, null=True)
    provincia_nacimiento = models.CharField(max_length=45, blank=True, null=True)
    canto_nacimiento = models.CharField(max_length=45, blank=True, null=True)
    ciudad_nacimiento = models.CharField(max_length=45, blank=True, null=True)
    provincia_residencia = models.CharField(max_length=45, blank=True, null=True)
    canto_residencia = models.CharField(max_length=45, blank=True, null=True)
    ciudad_residencia = models.CharField(max_length=45, blank=True, null=True)
    direccion_residencia = models.CharField(max_length=45, blank=True, null=True)
    sexo = models.CharField(max_length=45, blank=True, null=True)
    genero = models.CharField(max_length=45, blank=True, null=True)
    tipo_sangre = models.CharField(max_length=45, blank=True, null=True)
    estado_civil = models.CharField(max_length=45, blank=True, null=True)
    etnia = models.CharField(max_length=45, blank=True, null=True)
    correo_personal = models.EmailField(blank=True, null=True)
    correo_institucional = models.EmailField(blank=True, null=True)
    telefono = models.IntegerField(blank=True, null=True)  
    celular = models.IntegerField(blank=True, null=True) 
    celular_emergencia = models.CharField(max_length=45, blank=True, null=True)
    nombre_emergencia = models.CharField(max_length=45, blank=True, null=True)
    discapacidad = models.CharField(max_length=45, blank=True, null=True)

    def __str__(self):
        return f" {self.apellido} {self.nombre}"


@receiver(post_save, sender=Estudiante)
def crear_usuario_estudiante(sender, instance, created, **kwargs):
    if created and instance.usuario is None:
        username = str(instance.nui)  # aseguramos string
        user = User.objects.create_user(
            username=username,
            email=instance.correo_institucional,
            password='Alu_user8*',
            first_name=instance.nombre,
            last_name=instance.apellido,
        )
        group, _ = Group.objects.get_or_create(name='Estudiante')
        user.groups.add(group)

        # actualizamos solo el campo 'usuario' sin llamar a save()
        Estudiante.objects.filter(pk=instance.pk).update(usuario=user)

class Docente(models.Model):
    usuario = models.OneToOneField(User, on_delete=models.CASCADE, null=True, blank=True)  # Allow null user initially
    nui = models.IntegerField(unique=True, null=False, blank=False)  # Removed max_length
    apellido = models.CharField(max_length=45, blank=True, null=True)
    nombre = models.CharField(max_length=45, blank=True, null=True)
    fecha_nacimiento = models.CharField(max_length=45, blank=True, null=True)
    nacionalidad = models.CharField(max_length=45, blank=True, null=True)
    provincia_nacimiento = models.CharField(max_length=45, blank=True, null=True)
    canto_nacimiento = models.CharField(max_length=45, blank=True, null=True)
    ciudad_nacimiento = models.CharField(max_length=45, blank=True, null=True)
    provincia_residencia = models.CharField(max_length=45, blank=True, null=True)
    canto_residencia = models.CharField(max_length=45, blank=True, null=True)
    ciudad_residencia = models.CharField(max_length=45, blank=True, null=True)
    direccion_residencia = models.CharField(max_length=45, blank=True, null=True)
    sexo = models.CharField(max_length=45, blank=True, null=True)
    genero = models.CharField(max_length=45, blank=True, null=True)
    tipo_sangre = models.CharField(max_length=45, blank=True, null=True)
    estado_civil = models.CharField(max_length=45, blank=True, null=True)
    etnia = models.CharField(max_length=45, blank=True, null=True)
    correo_personal = models.EmailField(blank=True, null=True)
    correo_institucional = models.EmailField(blank=True, null=True)
    telefono = models.IntegerField(blank=True, null=True)  
    celular = models.IntegerField(blank=True, null=True) 
    celular_emergencia = models.CharField(max_length=45, blank=True, null=True)
    nombre_emergencia = models.CharField(max_length=45, blank=True, null=True)
    discapacidad = models.CharField(max_length=45, blank=True, null=True)

    def __str__(self):
        return f"{self.apellido},{self.nombre}"
 
class ProgramaEducativo(models.Model):
    nombre = models.CharField(max_length=255)
    modalidad = models.CharField(max_length=255)

    def __str__(self):
        return self.nombre
class PeriodoAcademico(models.Model):
    nombre = models.CharField(max_length=255)
    fecha_inicio = models.DateField()
    fecha_fin = models.DateField()
    activo = models.BooleanField(default=False)

    def __str__(self):
        return f"{self.nombre} ({self.fecha_inicio} - {self.fecha_fin})"
class Nivel(models.Model):
    nombre = models.CharField(max_length=255)
    programa = models.ForeignKey(ProgramaEducativo, on_delete=models.CASCADE)
    periodo = models.ForeignKey(PeriodoAcademico, on_delete=models.CASCADE)
    nivel = models.PositiveIntegerField()
    activo = models.BooleanField(default=True)

    def __str__(self):
        return f"{self.nombre} - {self.programa} - Nivel {self.nivel}"
class Materia(models.Model):
    nombre = models.CharField(max_length=255)
    docente = models.ForeignKey(Docente, on_delete=models.SET_NULL, null=True, blank=True) 

    nivel = models.ForeignKey(Nivel, on_delete=models.CASCADE)
    activo = models.BooleanField(default=True)
    id_moodle = models.PositiveIntegerField(null=True, blank=True)  # <- Nuevo campo

    def __str__(self):
        return f"{self.nombre} ({self.nivel.programa}, Nivel {self.nivel.nivel})"
class Matricula(models.Model):
    estudiante = models.ForeignKey("Estudiante", on_delete=models.CASCADE)
    materia = models.ForeignKey("Materia", on_delete=models.CASCADE)
    periodo = models.ForeignKey("PeriodoAcademico", on_delete=models.CASCADE)
    activo = models.BooleanField(default=True)

    def __str__(self):
        return f"{self.estudiante} - {self.materia} ({self.periodo})"

from django.db import models
from django.core.exceptions import ValidationError

class Calificacion(models.Model):
    matricula = models.ForeignKey('Matricula', on_delete=models.CASCADE)

    nota1_sem1 = models.DecimalField(max_digits=5, decimal_places=2, null=True, blank=True)
    nota2_sem1 = models.DecimalField(max_digits=5, decimal_places=2, null=True, blank=True)
    prueba_sem1 = models.DecimalField(max_digits=5, decimal_places=2, null=True, blank=True)
    examen_sem1 = models.DecimalField(max_digits=5, decimal_places=2, null=True, blank=True)

    nota1_sem2 = models.DecimalField(max_digits=5, decimal_places=2, null=True, blank=True)
    nota2_sem2 = models.DecimalField(max_digits=5, decimal_places=2, null=True, blank=True)
    prueba_sem2 = models.DecimalField(max_digits=5, decimal_places=2, null=True, blank=True)
    examen_sem2 = models.DecimalField(max_digits=5, decimal_places=2, null=True, blank=True)

    recuperacion = models.DecimalField(max_digits=5, decimal_places=2, null=True, blank=True)

    asistencia = models.DecimalField(
        max_digits=5,
        decimal_places=2,
        null=True,
        blank=True,
        help_text="Porcentaje de asistencia (0 a 100)"
    )

    aprobado = models.BooleanField(default=False)

    ESTADOS = [
        ('C', 'En curso'),
        ('A', 'Aprobado'),
        ('R', 'Recuperación'),
        ('P', 'Reprobado'),
    ]
    estado = models.CharField(max_length=1, choices=ESTADOS, default='C')

    nota_por_recuperacion = models.BooleanField(default=False)

    PONDERACIONES_SEM1 = [
        ("nota1_sem1", 0.15),
        ("nota2_sem1", 0.15),
        ("prueba_sem1", 0.30),
        ("examen_sem1", 0.40),
    ]

    PONDERACIONES_SEM2 = [
        ("nota1_sem2", 0.15),
        ("nota2_sem2", 0.15),
        ("prueba_sem2", 0.30),
        ("examen_sem2", 0.40),
    ]

    def promedio1(self):
        if all(getattr(self, campo) is not None for campo, _ in self.PONDERACIONES_SEM1):
            return round(sum(float(getattr(self, campo)) * peso for campo, peso in self.PONDERACIONES_SEM1), 2)
        return None

    def promedio2(self):
        if all(getattr(self, campo) is not None for campo, _ in self.PONDERACIONES_SEM2):
            return round(sum(float(getattr(self, campo)) * peso for campo, peso in self.PONDERACIONES_SEM2), 2)
        return None

    def nota_final(self):
     
        prom1 = self.promedio1()
        prom2 = self.promedio2()

        if prom1 is not None and prom2 is not None:
            promedio = round((prom1 + prom2) / 2, 2)

            if self.recuperacion is not None and self.recuperacion > 0:
                return round((promedio + float(self.recuperacion)) / 2, 2)
            return promedio

        return None

    def save(self, *args, **kwargs):
        final = self.nota_final()

        if final is not None:
            if final >= 7:
                self.estado = 'A'
                self.aprobado = True
            elif final >= 4:
                self.estado = 'R' if self.recuperacion is None or self.recuperacion == 0 else 'P'
                self.aprobado = False
            else:
                self.estado = 'P'
                self.aprobado = False
        else:
            self.estado = 'C'
            self.aprobado = False

        self.nota_por_recuperacion = self.recuperacion is not None and self.recuperacion > 0

        super().save(*args, **kwargs)

    def clean(self):
        for campo in (
            'nota1_sem1', 'nota2_sem1', 'prueba_sem1', 'examen_sem1',
            'nota1_sem2', 'nota2_sem2', 'prueba_sem2', 'examen_sem2',
            'recuperacion'
        ):
            valor = getattr(self, campo)
            if valor is not None and not (0 <= valor <= 10):
                raise ValidationError({campo: "La nota debe estar entre 0 y 10."})

        if self.asistencia is not None and not (0 <= self.asistencia <= 100):
            raise ValidationError({'asistencia': "La asistencia debe estar entre 0 y 100."})

    def __str__(self):
        nota = self.nota_final()
        nota_str = f"{nota:.2f}" if nota is not None else "Sin nota"
        estado_str = dict(self.ESTADOS).get(self.estado, "Desconocido")
        return f"{self.matricula.estudiante} - {self.matricula.materia} - {estado_str} - Nota Final: {nota_str}"
