from typing import Optional

from fastapi import APIRouter, Depends, HTTPException, Query
from sqlalchemy.orm import Session, joinedload

from ..db_models.internal import UsuarioAdmin
from ..db_models.platform import (
    Actividad, Alumno, Calificacion, Curso, Entrega,
    Matricula, Profesor, Progreso, Rol, Usuario,
)
from ..dependencies import get_current_admin, get_platform_db
from ..schemas.platform import (
    ActividadOut, AlumnoOut, CursoOut, EntregaOut,
    MatriculaOut, PlatformSummary, ProfesorOut, ProgresoOut, UsuarioOut,
)

router = APIRouter(prefix="/platform", tags=["Plataforma de Usuarios"])


# ── Summary ─────────────────────────────────────────────────────────────────────

@router.get("/summary", response_model=PlatformSummary, summary="Resumen de la plataforma de usuarios")
def platform_summary(
    db: Session = Depends(get_platform_db),
    _: UsuarioAdmin = Depends(get_current_admin),
):
    return PlatformSummary(
        total_users=db.query(Usuario).count(),
        active_users=db.query(Usuario).filter(Usuario.activo == True).count(),
        total_students=db.query(Alumno).count(),
        total_teachers=db.query(Profesor).count(),
        total_courses=db.query(Curso).count(),
        total_enrollments=db.query(Matricula).count(),
        total_activities=db.query(Actividad).count(),
        total_submissions=db.query(Entrega).count(),
    )


# ── Users ───────────────────────────────────────────────────────────────────────

@router.get("/users", summary="Lista de usuarios de la plataforma")
def get_users(
    page: int = Query(1, ge=1),
    page_size: int = Query(50, ge=1, le=200),
    rol: Optional[str] = Query(None, description="Filtrar por nombre de rol"),
    activo: Optional[bool] = Query(None),
    db: Session = Depends(get_platform_db),
    _: UsuarioAdmin = Depends(get_current_admin),
):
    q = db.query(Usuario).options(joinedload(Usuario.rol))
    if rol:
        q = q.join(Rol).filter(Rol.nombre == rol)
    if activo is not None:
        q = q.filter(Usuario.activo == activo)
    total = q.count()
    items = q.offset((page - 1) * page_size).limit(page_size).all()
    return {
        "total": total, "page": page, "page_size": page_size,
        "items": [UsuarioOut.model_validate(u) for u in items],
    }


@router.get("/users/{user_id}", response_model=UsuarioOut, summary="Datos de un usuario específico")
def get_user(
    user_id: int,
    db: Session = Depends(get_platform_db),
    _: UsuarioAdmin = Depends(get_current_admin),
):
    u = db.query(Usuario).options(joinedload(Usuario.rol)).filter(Usuario.id_usuario == user_id).first()
    if not u:
        raise HTTPException(status_code=404, detail="Usuario no encontrado")
    return UsuarioOut.model_validate(u)


# ── Students ─────────────────────────────────────────────────────────────────────

@router.get("/students", summary="Lista de alumnos")
def get_students(
    page: int = Query(1, ge=1),
    page_size: int = Query(50, ge=1, le=200),
    nivel: Optional[str] = Query(None),
    db: Session = Depends(get_platform_db),
    _: UsuarioAdmin = Depends(get_current_admin),
):
    q = db.query(Alumno).options(joinedload(Alumno.usuario).joinedload(Usuario.rol))
    if nivel:
        q = q.filter(Alumno.nivel == nivel)
    total = q.count()
    items = q.offset((page - 1) * page_size).limit(page_size).all()
    return {
        "total": total, "page": page, "page_size": page_size,
        "items": [AlumnoOut.model_validate(a) for a in items],
    }


@router.get("/students/{student_id}", response_model=AlumnoOut, summary="Datos de un alumno")
def get_student(
    student_id: int,
    db: Session = Depends(get_platform_db),
    _: UsuarioAdmin = Depends(get_current_admin),
):
    a = (
        db.query(Alumno)
        .options(joinedload(Alumno.usuario).joinedload(Usuario.rol))
        .filter(Alumno.id_alumno == student_id)
        .first()
    )
    if not a:
        raise HTTPException(status_code=404, detail="Alumno no encontrado")
    return AlumnoOut.model_validate(a)


# ── Teachers ──────────────────────────────────────────────────────────────────────

@router.get("/teachers", summary="Lista de profesores")
def get_teachers(
    page: int = Query(1, ge=1),
    page_size: int = Query(50, ge=1, le=200),
    db: Session = Depends(get_platform_db),
    _: UsuarioAdmin = Depends(get_current_admin),
):
    q = db.query(Profesor).options(joinedload(Profesor.usuario).joinedload(Usuario.rol))
    total = q.count()
    items = q.offset((page - 1) * page_size).limit(page_size).all()
    return {
        "total": total, "page": page, "page_size": page_size,
        "items": [ProfesorOut.model_validate(p) for p in items],
    }


# ── Courses ───────────────────────────────────────────────────────────────────────

@router.get("/courses", summary="Lista de cursos")
def get_courses(
    page: int = Query(1, ge=1),
    page_size: int = Query(50, ge=1, le=200),
    db: Session = Depends(get_platform_db),
    _: UsuarioAdmin = Depends(get_current_admin),
):
    q = db.query(Curso).options(
        joinedload(Curso.profesor).joinedload(Profesor.usuario).joinedload(Usuario.rol)
    )
    total = q.count()
    items = q.offset((page - 1) * page_size).limit(page_size).all()
    return {
        "total": total, "page": page, "page_size": page_size,
        "items": [CursoOut.model_validate(c) for c in items],
    }


@router.get("/courses/{course_id}", summary="Datos de un curso con actividades")
def get_course(
    course_id: int,
    db: Session = Depends(get_platform_db),
    _: UsuarioAdmin = Depends(get_current_admin),
):
    c = (
        db.query(Curso)
        .options(
            joinedload(Curso.profesor).joinedload(Profesor.usuario),
            joinedload(Curso.actividades),
        )
        .filter(Curso.id_curso == course_id)
        .first()
    )
    if not c:
        raise HTTPException(status_code=404, detail="Curso no encontrado")
    return {
        **CursoOut.model_validate(c).model_dump(),
        "actividades": [ActividadOut.model_validate(a) for a in c.actividades],
    }


# ── Enrollments ───────────────────────────────────────────────────────────────────

@router.get("/enrollments", summary="Lista de matrículas")
def get_enrollments(
    course_id: Optional[int] = Query(None),
    student_id: Optional[int] = Query(None),
    page: int = Query(1, ge=1),
    page_size: int = Query(50, ge=1, le=200),
    db: Session = Depends(get_platform_db),
    _: UsuarioAdmin = Depends(get_current_admin),
):
    q = db.query(Matricula)
    if course_id:
        q = q.filter(Matricula.id_curso == course_id)
    if student_id:
        q = q.filter(Matricula.id_alumno == student_id)
    total = q.count()
    items = q.offset((page - 1) * page_size).limit(page_size).all()
    return {
        "total": total, "page": page, "page_size": page_size,
        "items": [MatriculaOut.model_validate(m) for m in items],
    }


# ── Activities ────────────────────────────────────────────────────────────────────

@router.get("/activities", summary="Lista de actividades")
def get_activities(
    course_id: Optional[int] = Query(None),
    page: int = Query(1, ge=1),
    page_size: int = Query(50, ge=1, le=200),
    db: Session = Depends(get_platform_db),
    _: UsuarioAdmin = Depends(get_current_admin),
):
    q = db.query(Actividad)
    if course_id:
        q = q.filter(Actividad.id_curso == course_id)
    total = q.count()
    items = q.offset((page - 1) * page_size).limit(page_size).all()
    return {
        "total": total, "page": page, "page_size": page_size,
        "items": [ActividadOut.model_validate(a) for a in items],
    }


# ── Submissions ───────────────────────────────────────────────────────────────────

@router.get("/submissions", summary="Lista de entregas")
def get_submissions(
    activity_id: Optional[int] = Query(None),
    student_id: Optional[int] = Query(None),
    estado: Optional[str] = Query(None, description="pendiente | entregado | calificado"),
    page: int = Query(1, ge=1),
    page_size: int = Query(50, ge=1, le=200),
    db: Session = Depends(get_platform_db),
    _: UsuarioAdmin = Depends(get_current_admin),
):
    q = db.query(Entrega).options(joinedload(Entrega.calificacion))
    if activity_id:
        q = q.filter(Entrega.id_actividad == activity_id)
    if student_id:
        q = q.filter(Entrega.id_alumno == student_id)
    if estado:
        q = q.filter(Entrega.estado == estado)
    total = q.count()
    items = q.offset((page - 1) * page_size).limit(page_size).all()
    return {
        "total": total, "page": page, "page_size": page_size,
        "items": [EntregaOut.model_validate(e) for e in items],
    }


# ── Progress ──────────────────────────────────────────────────────────────────────

@router.get("/progress", summary="Progreso de alumnos en cursos")
def get_progress(
    course_id: Optional[int] = Query(None),
    student_id: Optional[int] = Query(None),
    page: int = Query(1, ge=1),
    page_size: int = Query(50, ge=1, le=200),
    db: Session = Depends(get_platform_db),
    _: UsuarioAdmin = Depends(get_current_admin),
):
    q = db.query(Progreso)
    if course_id:
        q = q.filter(Progreso.id_curso == course_id)
    if student_id:
        q = q.filter(Progreso.id_alumno == student_id)
    total = q.count()
    items = q.offset((page - 1) * page_size).limit(page_size).all()
    return {
        "total": total, "page": page, "page_size": page_size,
        "items": [ProgresoOut.model_validate(p) for p in items],
    }
