from datetime import datetime, timezone
from sqlalchemy import Column, Integer, String, Boolean, Text, DateTime, Numeric, ForeignKey, UniqueConstraint
from sqlalchemy.orm import DeclarativeBase, relationship

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")
    alumno        = relationship("Alumno", back_populates="usuario", uselist=False)
    profesor      = relationship("Profesor", back_populates="usuario", uselist=False)
    credencial    = relationship("Credencial", 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 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 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))
    cursos       = relationship("Curso", back_populates="profesor")
    usuario      = relationship("Usuario", back_populates="profesor")

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) # Store as "HH:MM" for simplicity in JSON, mapped to TIME in DB
    hora_fin    = Column(String(5), nullable=False)
    aula        = Column(String(50))
    curso       = relationship("Curso")

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)
    curso       = relationship("Curso")
    estudiantes = relationship("ProyectoEstudiante", back_populates="proyecto")

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)
    proyecto    = relationship("Proyecto", back_populates="estudiantes")
    alumno      = relationship("Alumno")

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))
    curso       = relationship("Curso")
