#!/usr/bin/env python3
"""
Seed de la base de datos de la plataforma de usuarios.

Crea: roles, usuarios, credenciales, profesores, alumnos,
      cursos, matrículas, actividades, entregas, calificaciones y progreso.

Uso (desde user_platform/):
    python seed.py

La contraseña por defecto de todos los usuarios es: Password123!
"""

import os
import random
from datetime import datetime, timedelta, timezone
from decimal import Decimal

# ── DB URL (lee el .env raíz del proyecto) ──────────────────────────────────────
def _read_env(path: str) -> dict[str, str]:
    result: dict[str, str] = {}
    if os.path.exists(path):
        with open(path) as f:
            for line in f:
                line = line.strip()
                if line and not line.startswith("#") and "=" in line:
                    key, _, val = line.partition("=")
                    result[key.strip()] = val.strip()
    return result

# Busca el .env raíz subiendo desde user_platform/
_here = os.path.dirname(os.path.abspath(__file__))
env = _read_env(os.path.join(_here, "..", ".env"))

pg_user = env.get("PLATFORM_DB_USER", "user-database-user")
pg_pass = env.get("PLATFORM_DB_PASSWORD", "")
pg_db   = env.get("PLATFORM_DB_NAME", "user-database")
pg_port = env.get("PLATFORM_DB_PORT", "55557")
DB_URL  = os.environ.get("PLATFORM_DB_URL", f"postgresql://{pg_user}:{pg_pass}@localhost:{pg_port}/{pg_db}")

# ── ORM ─────────────────────────────────────────────────────────────────────────
from sqlalchemy import create_engine, Column, Integer, String, Boolean, Text, DateTime, Numeric, ForeignKey, UniqueConstraint
from sqlalchemy.orm import sessionmaker, DeclarativeBase, relationship
from passlib.context import CryptContext

pwd_ctx = CryptContext(schemes=["bcrypt"], deprecated="auto")

engine = create_engine(DB_URL, pool_pre_ping=True)
Session = sessionmaker(bind=engine)


class Base(DeclarativeBase):
    pass


class Rol(Base):
    __tablename__ = "roles"
    id_rol   = Column(Integer, primary_key=True)
    nombre   = Column(String(50), unique=True, nullable=False)
    usuarios = relationship("Usuario", back_populates="rol")


class Usuario(Base):
    __tablename__ = "usuarios"
    id_usuario    = Column(Integer, primary_key=True)
    nombre        = Column(String(100), nullable=False)
    apellidos     = Column(String(150))
    email         = Column(String(150), unique=True, nullable=False)
    fecha_creacion = Column(DateTime, default=lambda: datetime.now(timezone.utc))
    activo        = Column(Boolean, default=True)
    id_rol        = Column(Integer, ForeignKey("roles.id_rol"), nullable=False)
    rol           = relationship("Rol", back_populates="usuarios")
    credencial    = relationship("Credencial", back_populates="usuario", uselist=False)
    profesor      = relationship("Profesor", back_populates="usuario", uselist=False)
    alumno        = relationship("Alumno", back_populates="usuario", uselist=False)


class Credencial(Base):
    __tablename__ = "credenciales"
    id_credencial = Column(Integer, primary_key=True)
    id_usuario    = Column(Integer, ForeignKey("usuarios.id_usuario", ondelete="CASCADE"), unique=True)
    password_hash = Column(Text, nullable=False)
    ultimo_login  = Column(DateTime)
    usuario       = relationship("Usuario", back_populates="credencial")


class Profesor(Base):
    __tablename__ = "profesores"
    id_profesor  = Column(Integer, primary_key=True)
    id_usuario   = Column(Integer, ForeignKey("usuarios.id_usuario", ondelete="CASCADE"), unique=True)
    especialidad = Column(String(100))
    usuario      = relationship("Usuario", back_populates="profesor")
    cursos       = relationship("Curso", back_populates="profesor")


class Alumno(Base):
    __tablename__ = "alumnos"
    id_alumno  = Column(Integer, primary_key=True)
    id_usuario = Column(Integer, ForeignKey("usuarios.id_usuario", ondelete="CASCADE"), unique=True)
    nivel      = Column(String(50))
    usuario    = relationship("Usuario", back_populates="alumno")
    matriculas = relationship("Matricula", back_populates="alumno")
    entregas   = relationship("Entrega", back_populates="alumno")
    progreso   = relationship("Progreso", back_populates="alumno")


class Curso(Base):
    __tablename__ = "cursos"
    id_curso      = Column(Integer, primary_key=True)
    nombre        = Column(String(150), nullable=False)
    descripcion   = Column(Text)
    fecha_creacion = Column(DateTime, default=lambda: datetime.now(timezone.utc))
    id_profesor   = Column(Integer, ForeignKey("profesores.id_profesor"), nullable=False)
    profesor      = relationship("Profesor", back_populates="cursos")
    matriculas    = relationship("Matricula", back_populates="curso")
    actividades   = relationship("Actividad", back_populates="curso")
    progreso      = relationship("Progreso", back_populates="curso")


class Matricula(Base):
    __tablename__ = "matriculas"
    __table_args__ = (UniqueConstraint("id_alumno", "id_curso"),)
    id_matricula   = Column(Integer, primary_key=True)
    id_alumno      = Column(Integer, ForeignKey("alumnos.id_alumno", ondelete="CASCADE"))
    id_curso       = Column(Integer, ForeignKey("cursos.id_curso", ondelete="CASCADE"))
    fecha_matricula = Column(DateTime, default=lambda: datetime.now(timezone.utc))
    alumno         = relationship("Alumno", back_populates="matriculas")
    curso          = relationship("Curso", back_populates="matriculas")


class Actividad(Base):
    __tablename__ = "actividades"
    id_actividad     = Column(Integer, primary_key=True)
    titulo           = Column(String(200), nullable=False)
    descripcion      = Column(Text)
    fecha_publicacion = Column(DateTime, default=lambda: datetime.now(timezone.utc))
    fecha_entrega    = Column(DateTime)
    puntuacion_maxima = Column(Numeric(5, 2))
    id_curso         = Column(Integer, ForeignKey("cursos.id_curso", ondelete="CASCADE"))
    curso            = relationship("Curso", back_populates="actividades")
    entregas         = relationship("Entrega", back_populates="actividad")


class Entrega(Base):
    __tablename__ = "entregas"
    id_entrega   = Column(Integer, primary_key=True)
    id_actividad = Column(Integer, ForeignKey("actividades.id_actividad", ondelete="CASCADE"))
    id_alumno    = Column(Integer, ForeignKey("alumnos.id_alumno", ondelete="CASCADE"))
    fecha_entrega = Column(DateTime, default=lambda: datetime.now(timezone.utc))
    contenido    = Column(Text)
    estado       = Column(String(50), default="calificado")
    actividad    = relationship("Actividad", back_populates="entregas")
    alumno       = relationship("Alumno", back_populates="entregas")
    calificacion = relationship("Calificacion", back_populates="entrega", uselist=False)


class Calificacion(Base):
    __tablename__ = "calificaciones"
    id_calificacion  = Column(Integer, primary_key=True)
    id_entrega       = Column(Integer, ForeignKey("entregas.id_entrega", ondelete="CASCADE"), unique=True)
    nota             = Column(Numeric(5, 2))
    observaciones    = Column(Text)
    fecha_calificacion = Column(DateTime, default=lambda: datetime.now(timezone.utc))
    entrega          = relationship("Entrega", back_populates="calificacion")


class Progreso(Base):
    __tablename__ = "progreso"
    __table_args__ = (UniqueConstraint("id_alumno", "id_curso"),)
    id_progreso = Column(Integer, primary_key=True)
    id_alumno   = Column(Integer, ForeignKey("alumnos.id_alumno", ondelete="CASCADE"))
    id_curso    = Column(Integer, ForeignKey("cursos.id_curso", ondelete="CASCADE"))
    porcentaje  = Column(Numeric(5, 2), default=0)
    alumno      = relationship("Alumno", back_populates="progreso")
    curso       = relationship("Curso", back_populates="progreso")


class Horario(Base):
    __tablename__ = "horarios"
    id_horario  = Column(Integer, primary_key=True)
    id_curso    = Column(Integer, ForeignKey("cursos.id_curso", ondelete="CASCADE"))
    dia_semana  = Column(Integer, nullable=False)
    hora_inicio = Column(String(5), nullable=False)
    hora_fin    = Column(String(5), nullable=False)
    aula        = Column(String(50))

class Proyecto(Base):
    __tablename__ = "proyectos"
    id_proyecto = Column(Integer, primary_key=True)
    id_curso    = Column(Integer, ForeignKey("cursos.id_curso", ondelete="CASCADE"))
    titulo      = Column(String(200), nullable=False)
    descripcion = Column(Text)
    fecha_entrega = Column(DateTime)
    estado      = Column(String(50), default="en curso")
    porcentaje_completado = Column(Numeric(5, 2), default=0)

class ProyectoEstudiante(Base):
    __tablename__ = "proyectos_estudiantes"
    id_proyecto = Column(Integer, ForeignKey("proyectos.id_proyecto", ondelete="CASCADE"), primary_key=True)
    id_alumno   = Column(Integer, ForeignKey("alumnos.id_alumno", ondelete="CASCADE"), primary_key=True)

class Examen(Base):
    __tablename__ = "examenes"
    id_examen   = Column(Integer, primary_key=True)
    id_curso    = Column(Integer, ForeignKey("cursos.id_curso", ondelete="CASCADE"))
    titulo      = Column(String(200), nullable=False)
    temario     = Column(Text)
    fecha       = Column(DateTime, nullable=False)
    duracion_minutos = Column(Integer, nullable=False)
    modalidad   = Column(String(50))


# ── Data ─────────────────────────────────────────────────────────────────────────

DEFAULT_PASSWORD = pwd_ctx.hash("Password123!")

ROLES = ["admin", "profesor", "estudiante"]

ADMINS = [
    {"nombre": "Emmanuel", "apellidos": "Bizimana", "email": "admin@opendata.edu"},
]

TEACHERS = [
    {"nombre": "Sarah",    "apellidos": "Kamau",      "email": "s.kamau@opendata.edu",     "especialidad": "Mathematics"},
    {"nombre": "Patrick",  "apellidos": "Habimana",   "email": "p.habimana@opendata.edu",  "especialidad": "Science"},
    {"nombre": "Aline",    "apellidos": "Nkurunziza", "email": "a.nkurunziza@opendata.edu","especialidad": "English"},
    {"nombre": "Moses",    "apellidos": "Kato",       "email": "m.kato@opendata.edu",      "especialidad": "ICT"},
    {"nombre": "Faith",    "apellidos": "Okello",     "email": "f.okello@opendata.edu",    "especialidad": "History & Civics"},
    {"nombre": "Neema",    "apellidos": "Mushi",      "email": "n.mushi@opendata.edu",     "especialidad": "Geography"},
    {"nombre": "Samuel",   "apellidos": "Otieno",     "email": "s.otieno@opendata.edu",    "especialidad": "Biology & Chemistry"},
]

STUDENTS = [
    {"nombre": "Grace",    "apellidos": "Uwimana",    "email": "g.uwimana@students.edu",   "nivel": "Secondary 5"},
    {"nombre": "John",     "apellidos": "Mwangi",     "email": "j.mwangi@students.edu",    "nivel": "Secondary 3"},
    {"nombre": "Claudine", "apellidos": "Bizimana",   "email": "c.bizimana@students.edu",  "nivel": "Secondary 2"},
    {"nombre": "Peter",    "apellidos": "Habimana",   "email": "p.habimana2@students.edu", "nivel": "Secondary 4"},
    {"nombre": "Amina",    "apellidos": "Kamau",      "email": "a.kamau@students.edu",     "nivel": "Secondary 1"},
    {"nombre": "David",    "apellidos": "Okello",     "email": "d.okello@students.edu",    "nivel": "Secondary 6"},
    {"nombre": "Fatuma",   "apellidos": "Otieno",     "email": "f.otieno@students.edu",    "nivel": "Secondary 3"},
    {"nombre": "Joseph",   "apellidos": "Kato",       "email": "j.kato@students.edu",      "nivel": "Secondary 2"},
    {"nombre": "Esperance","apellidos": "Nkurunziza", "email": "e.nkurunziza@students.edu","nivel": "Secondary 5"},
    {"nombre": "Ali",      "apellidos": "Mushi",      "email": "a.mushi@students.edu",     "nivel": "Secondary 4"},
    {"nombre": "Zawadi",   "apellidos": "Habimana",   "email": "z.habimana@students.edu",  "nivel": "Secondary 1"},
    {"nombre": "Rehema",   "apellidos": "Uwimana",    "email": "r.uwimana@students.edu",   "nivel": "Secondary 3"},
    {"nombre": "Baraka",   "apellidos": "Mwangi",     "email": "b.mwangi@students.edu",    "nivel": "Secondary 6"},
    {"nombre": "Solange",  "apellidos": "Kato",       "email": "s.kato@students.edu",      "nivel": "Secondary 2"},
    {"nombre": "Omar",     "apellidos": "Otieno",     "email": "o.otieno@students.edu",    "nivel": "Secondary 4"},
    {"nombre": "Immaculée","apellidos": "Bizimana",   "email": "i.bizimana@students.edu",  "nivel": "Secondary 5"},
    {"nombre": "Mussa",    "apellidos": "Kamau",      "email": "m.kamau@students.edu",     "nivel": "Secondary 1"},
    {"nombre": "Vestine",  "apellidos": "Okello",     "email": "v.okello@students.edu",    "nivel": "Secondary 3"},
    {"nombre": "Patrick",  "apellidos": "Mushi",      "email": "p.mushi@students.edu",     "nivel": "Secondary 6"},
    {"nombre": "Dativa",   "apellidos": "Nkurunziza", "email": "d.nkurunziza@students.edu","nivel": "Secondary 2"},
]

COURSES = [
    {
        "nombre": "Advanced Mathematics — Secondary 5 & 6",
        "descripcion": "Álgebra lineal, cálculo diferencial, estadística aplicada y resolución de problemas complejos.",
        "teacher_email": "s.kamau@opendata.edu",
    },
    {
        "nombre": "English Language & Literature",
        "descripcion": "Comprensión lectora, escritura académica, análisis literario y comunicación oral.",
        "teacher_email": "a.nkurunziza@opendata.edu",
    },
    {
        "nombre": "Integrated Science — Secondary 1 & 2",
        "descripcion": "Fundamentos de biología, química y física con enfoque experimental.",
        "teacher_email": "p.habimana@opendata.edu",
    },
    {
        "nombre": "ICT & Digital Literacy",
        "descripcion": "Ofimática, programación básica, seguridad digital y gestión de datos.",
        "teacher_email": "m.kato@opendata.edu",
    },
    {
        "nombre": "History, Civics & Social Studies",
        "descripcion": "Historia de África del Este, gobierno, derechos humanos y ciudadanía activa.",
        "teacher_email": "f.okello@opendata.edu",
    },
    {
        "nombre": "Geography & Environment",
        "descripcion": "Geografía física y humana, cambio climático y gestión de recursos naturales.",
        "teacher_email": "n.mushi@opendata.edu",
    },
    {
        "nombre": "Biology & Chemistry — Secondary 4 & 5",
        "descripcion": "Biología celular, genética, reacciones químicas orgánicas e inorgánicas.",
        "teacher_email": "s.otieno@opendata.edu",
    },
]

ACTIVITY_TEMPLATES = [
    {
        "titulo": "Tarea 1 — Evaluación inicial",
        "descripcion": "Evaluación de conocimientos previos y diagnóstico del nivel del estudiante.",
        "puntuacion_maxima": Decimal("20.00"),
        "dias_publicacion": -60,
        "dias_entrega": -55,
    },
    {
        "titulo": "Cuestionario — Trimestre 1",
        "descripcion": "Cuestionario de seguimiento sobre los contenidos del primer trimestre.",
        "puntuacion_maxima": Decimal("30.00"),
        "dias_publicacion": -40,
        "dias_entrega": -35,
    },
    {
        "titulo": "Proyecto colaborativo",
        "descripcion": "Trabajo en grupo sobre un caso de estudio real relacionado con la asignatura.",
        "puntuacion_maxima": Decimal("50.00"),
        "dias_publicacion": -25,
        "dias_entrega": -15,
    },
    {
        "titulo": "Examen Parcial — Trimestre 2",
        "descripcion": "Evaluación escrita de los contenidos del segundo trimestre.",
        "puntuacion_maxima": Decimal("40.00"),
        "dias_publicacion": -10,
        "dias_entrega": -5,
    },
    {
        "titulo": "Entrega final — Portfolio",
        "descripcion": "Portfolio de trabajos realizados durante el curso con reflexión personal.",
        "puntuacion_maxima": Decimal("60.00"),
        "dias_publicacion": -3,
        "dias_entrega": 10,
    },
]

SUBMISSION_TEXTS = [
    "He revisado el material y completado todos los ejercicios propuestos.",
    "Adjunto mi trabajo con las correcciones indicadas en clase.",
    "He realizado la tarea individualmente siguiendo las instrucciones del profesor.",
    "Incluyo referencias adicionales que encontré durante la investigación.",
    "Trabajo completado. Tuve dificultades con la parte práctica pero lo resolví.",
]


# ── Seed logic ───────────────────────────────────────────────────────────────────

def seed():
    print("\n=== Seed: Plataforma de Usuarios ===\n")

    Base.metadata.create_all(bind=engine)
    print("✓ Esquema verificado")

    db = Session()
    random.seed(42)

    try:
        # ── Roles
        rol_map: dict[str, Rol] = {}
        for nombre in ROLES:
            r = db.query(Rol).filter(Rol.nombre == nombre).first()
            if not r:
                r = Rol(nombre=nombre)
                db.add(r)
                db.flush()
            rol_map[nombre] = r
        db.commit()
        print(f"✓ Roles: {list(rol_map.keys())}")

        # ── Admins
        for data in ADMINS:
            if db.query(Usuario).filter(Usuario.email == data["email"]).first():
                continue
            u = Usuario(**data, id_rol=rol_map["admin"].id_rol)
            db.add(u)
            db.flush()
            db.add(Credencial(id_usuario=u.id_usuario, password_hash=DEFAULT_PASSWORD))
        db.commit()
        print(f"✓ Admins: {len(ADMINS)}")

        # ── Teachers
        profesor_map: dict[str, Profesor] = {}
        for data in TEACHERS:
            u = db.query(Usuario).filter(Usuario.email == data["email"]).first()
            if not u:
                u = Usuario(
                    nombre=data["nombre"], apellidos=data["apellidos"],
                    email=data["email"], id_rol=rol_map["profesor"].id_rol,
                )
                db.add(u)
                db.flush()
                db.add(Credencial(id_usuario=u.id_usuario, password_hash=DEFAULT_PASSWORD))
            p = db.query(Profesor).filter(Profesor.id_usuario == u.id_usuario).first()
            if not p:
                p = Profesor(id_usuario=u.id_usuario, especialidad=data["especialidad"])
                db.add(p)
                db.flush()
            profesor_map[data["email"]] = p
        db.commit()
        print(f"✓ Profesores: {len(TEACHERS)}")

        # ── Students
        alumno_list: list[Alumno] = []
        for data in STUDENTS:
            u = db.query(Usuario).filter(Usuario.email == data["email"]).first()
            if not u:
                u = Usuario(
                    nombre=data["nombre"], apellidos=data["apellidos"],
                    email=data["email"], id_rol=rol_map["estudiante"].id_rol,
                )
                db.add(u)
                db.flush()
                db.add(Credencial(id_usuario=u.id_usuario, password_hash=DEFAULT_PASSWORD))
            a = db.query(Alumno).filter(Alumno.id_usuario == u.id_usuario).first()
            if not a:
                a = Alumno(id_usuario=u.id_usuario, nivel=data["nivel"])
                db.add(a)
                db.flush()
            alumno_list.append(a)
        db.commit()
        print(f"✓ Alumnos: {len(STUDENTS)}")

        # ── Courses
        curso_list: list[Curso] = []
        for data in COURSES:
            c = db.query(Curso).filter(Curso.nombre == data["nombre"]).first()
            if not c:
                profesor = profesor_map[data["teacher_email"]]
                c = Curso(
                    nombre=data["nombre"],
                    descripcion=data["descripcion"],
                    id_profesor=profesor.id_profesor,
                    fecha_creacion=datetime.now(timezone.utc) - timedelta(days=90),
                )
                db.add(c)
                db.flush()
            curso_list.append(c)
        db.commit()
        print(f"✓ Cursos: {len(COURSES)}")

        # ── Horarios, Proyectos, Examenes
        horario_count = 0
        proyecto_count = 0
        examen_count = 0
        proyecto_list: list[Proyecto] = []
        for curso in curso_list:
            # Horarios
            dias = random.sample([1, 2, 3, 4, 5], 2)
            for dia in dias:
                h_inicio = random.choice(["08:00", "10:00", "12:00", "14:00"])
                h_fin = f"{int(h_inicio[:2])+2:02d}:00"
                aula = random.choice(["Sala Digital A", "Sala Digital B", "Lab 1", "Lab 2", "Aula 101"])
                h = Horario(id_curso=curso.id_curso, dia_semana=dia, hora_inicio=h_inicio, hora_fin=h_fin, aula=aula)
                db.add(h)
                horario_count += 1
            
            # Proyectos
            now = datetime.now(timezone.utc)
            p1 = Proyecto(id_curso=curso.id_curso, titulo=f"Proyecto Final: {curso.nombre}", descripcion="Aplicar los conceptos del curso en un caso práctico.", fecha_entrega=now + timedelta(days=30), estado="en curso", porcentaje_completado=Decimal(str(random.randint(10, 80))))
            p2 = Proyecto(id_curso=curso.id_curso, titulo=f"Investigación: {curso.nombre}", descripcion="Investigación bibliográfica y presentación.", fecha_entrega=now - timedelta(days=10), estado="entregado", porcentaje_completado=Decimal("100.00"))
            db.add_all([p1, p2])
            db.flush()
            proyecto_list.extend([p1, p2])
            proyecto_count += 2

            # Examenes
            e1 = Examen(id_curso=curso.id_curso, titulo=f"Examen Parcial", temario="Unidades 1 a 3", fecha=now - timedelta(days=5), duracion_minutos=90, modalidad="Presencial")
            e2 = Examen(id_curso=curso.id_curso, titulo=f"Examen Final", temario="Todo el temario", fecha=now + timedelta(days=25), duracion_minutos=120, modalidad="Online")
            db.add_all([e1, e2])
            examen_count += 2
        
        db.commit()
        print(f"✓ Horarios: {horario_count}, Proyectos: {proyecto_count}, Exámenes: {examen_count}")

        # ── Activities (5 per course)
        actividad_map: dict[int, list[Actividad]] = {}
        for curso in curso_list:
            actividad_map[curso.id_curso] = []
            for tmpl in ACTIVITY_TEMPLATES:
                titulo_full = f"{curso.nombre.split('—')[0].strip()} — {tmpl['titulo']}"
                a = db.query(Actividad).filter(Actividad.titulo == titulo_full).first()
                if not a:
                    now = datetime.now(timezone.utc)
                    a = Actividad(
                        titulo=titulo_full,
                        descripcion=tmpl["descripcion"],
                        puntuacion_maxima=tmpl["puntuacion_maxima"],
                        id_curso=curso.id_curso,
                        fecha_publicacion=now + timedelta(days=tmpl["dias_publicacion"]),
                        fecha_entrega=now + timedelta(days=tmpl["dias_entrega"]),
                    )
                    db.add(a)
                    db.flush()
                actividad_map[curso.id_curso].append(a)
        db.commit()
        total_acts = sum(len(v) for v in actividad_map.values())
        print(f"✓ Actividades: {total_acts}")

        # ── Enrollments: cada alumno en 3-4 cursos aleatorios
        matricula_count = 0
        entrega_count = 0
        for alumno in alumno_list:
            n_cursos = random.randint(3, 5)
            cursos_alumno = random.sample(curso_list, min(n_cursos, len(curso_list)))

            for curso in cursos_alumno:
                # Matrícula
                m = db.query(Matricula).filter(
                    Matricula.id_alumno == alumno.id_alumno,
                    Matricula.id_curso == curso.id_curso,
                ).first()
                if not m:
                    m = Matricula(
                        id_alumno=alumno.id_alumno,
                        id_curso=curso.id_curso,
                        fecha_matricula=datetime.now(timezone.utc) - timedelta(days=85),
                    )
                    db.add(m)
                    db.flush()
                    matricula_count += 1

                # Entregas y calificaciones (solo actividades ya cerradas)
                actividades_cerradas = [
                    a for a in actividad_map[curso.id_curso]
                    if a.fecha_entrega and a.fecha_entrega.replace(tzinfo=timezone.utc) < datetime.now(timezone.utc)
                ]
                notas: list[float] = []
                for actividad in actividades_cerradas:
                    e = db.query(Entrega).filter(
                        Entrega.id_alumno == alumno.id_alumno,
                        Entrega.id_actividad == actividad.id_actividad,
                    ).first()
                    if not e:
                        entrega_fecha = actividad.fecha_entrega - timedelta(hours=random.randint(1, 48))
                        e = Entrega(
                            id_actividad=actividad.id_actividad,
                            id_alumno=alumno.id_alumno,
                            fecha_entrega=entrega_fecha,
                            contenido=random.choice(SUBMISSION_TEXTS),
                            estado="calificado",
                        )
                        db.add(e)
                        db.flush()
                        entrega_count += 1

                        # Nota: distribución realista centrada en 60-85
                        max_nota = float(actividad.puntuacion_maxima)
                        base_pct = random.gauss(0.72, 0.15)
                        base_pct = max(0.3, min(1.0, base_pct))
                        nota = round(base_pct * max_nota, 2)
                        notas.append(nota / max_nota * 100)

                        obs_list = [
                            "Buen trabajo, sigue así.",
                            "Necesita mejorar la argumentación.",
                            "Excelente presentación y contenido.",
                            "Trabajo correcto pero le falta profundidad.",
                            "Muy buen desempeño.",
                        ]
                        db.add(Calificacion(
                            id_entrega=e.id_entrega,
                            nota=Decimal(str(nota)),
                            observaciones=random.choice(obs_list),
                            fecha_calificacion=entrega_fecha + timedelta(days=random.randint(1, 5)),
                        ))

                # Progreso del alumno en este curso
                if actividades_cerradas:
                    entregadas = len(actividades_cerradas)
                    total_act = len(actividad_map[curso.id_curso])
                    pct_entrega = (entregadas / total_act) * 100
                    pct_nota = (sum(notas) / len(notas)) if notas else 0
                    porcentaje = round((pct_entrega * 0.4 + pct_nota * 0.6), 2)

                    prog = db.query(Progreso).filter(
                        Progreso.id_alumno == alumno.id_alumno,
                        Progreso.id_curso == curso.id_curso,
                    ).first()
                    if not prog:
                        db.add(Progreso(
                            id_alumno=alumno.id_alumno,
                            id_curso=curso.id_curso,
                            porcentaje=Decimal(str(porcentaje)),
                        ))

                # Asignar proyectos del curso al alumno
                proyectos_curso = [p for p in proyecto_list if p.id_curso == curso.id_curso]
                for p in proyectos_curso:
                    pe = db.query(ProyectoEstudiante).filter(ProyectoEstudiante.id_proyecto == p.id_proyecto, ProyectoEstudiante.id_alumno == alumno.id_alumno).first()
                    if not pe:
                        db.add(ProyectoEstudiante(id_proyecto=p.id_proyecto, id_alumno=alumno.id_alumno))

        db.commit()
        print(f"✓ Matrículas:  {matricula_count}")
        print(f"✓ Entregas:    {entrega_count}")
        print(f"✓ Progreso calculado")

        # ── Resumen final
        print("\n─── Resumen ────────────────────────────────")
        print(f"  Usuarios totales:  {db.query(Usuario).count()}")
        print(f"  Profesores:        {db.query(Profesor).count()}")
        print(f"  Alumnos:           {db.query(Alumno).count()}")
        print(f"  Cursos:            {db.query(Curso).count()}")
        print(f"  Actividades:       {db.query(Actividad).count()}")
        print(f"  Entregas:          {db.query(Entrega).count()}")
        print(f"  Calificaciones:    {db.query(Calificacion).count()}")
        print(f"  Progreso registros:{db.query(Progreso).count()}")
        print(f"  Horarios:          {db.query(Horario).count()}")
        print(f"  Proyectos:         {db.query(Proyecto).count()}")
        print(f"  Exámenes:          {db.query(Examen).count()}")
        print("────────────────────────────────────────────")
        print("\n  Contraseña de todos los usuarios: Password123!")
        print("  Ya puedes hacer login desde la API.\n")

    except Exception as e:
        db.rollback()
        print(f"\n✗ Error durante el seed: {e}")
        raise
    finally:
        db.close()


if __name__ == "__main__":
    seed()
