from fastapi import APIRouter, Depends, HTTPException, Body
from pydantic import BaseModel
from sqlalchemy.orm import Session, joinedload
from sqlalchemy import func
from datetime import datetime, timezone
from ..database import get_db
from ..models import Alumno, Curso, Matricula, Actividad, Entrega, Calificacion, Progreso, Profesor, Horario, Proyecto, ProyectoEstudiante, Examen
from .auth import get_current_student

router = APIRouter(prefix="/api/student", tags=["Student"])

class TaskSubmit(BaseModel):
    contenido: str

class ProjectProgress(BaseModel):
    progress: float

@router.get("/dashboard")
def get_dashboard(student: Alumno = Depends(get_current_student), db: Session = Depends(get_db)):
    student_id = student.id_alumno
    alumno = db.query(Alumno).options(joinedload(Alumno.usuario)).filter(Alumno.id_alumno == student_id).first()
    
    progresos = db.query(Progreso).filter(Progreso.id_alumno == student_id).all()
    avg_progress = sum(float(p.porcentaje) for p in progresos) / len(progresos) if progresos else 0
    
    # Gamification mechanics
    xp = int(avg_progress * 150)
    level = max(1, xp // 1000)
    streak = 12 # Hardcoded for demo purposes
    
    matriculas = db.query(Matricula).filter(Matricula.id_alumno == student_id).all()
    curso_ids = [m.id_curso for m in matriculas]
    active_courses = len(curso_ids)

    pending_tasks = 0
    if curso_ids:
        actividades = db.query(Actividad).filter(Actividad.id_curso.in_(curso_ids)).all()
        now = datetime.now(timezone.utc)
        for a in actividades:
            e = db.query(Entrega).filter(Entrega.id_actividad == a.id_actividad, Entrega.id_alumno == student_id).first()
            if not e and (not a.fecha_entrega or a.fecha_entrega.replace(tzinfo=timezone.utc) >= now):
                pending_tasks += 1

    return {
        "id": alumno.id_alumno,
        "name": f"{alumno.usuario.nombre} {alumno.usuario.apellidos or ''}".strip(),
        "email": alumno.usuario.email,
        "level_name": alumno.nivel,
        "xp": xp,
        "level": level,
        "streak": streak,
        "avg_progress": round(avg_progress, 1),
        "gpa": round(avg_progress * 0.1, 1), # Simulated GPA 0-10
        "active_courses": active_courses,
        "pending_tasks": pending_tasks
    }

@router.get("/courses")
def get_courses(student: Alumno = Depends(get_current_student), db: Session = Depends(get_db)):
    student_id = student.id_alumno
    matriculas = db.query(Matricula).options(
        joinedload(Matricula.curso).joinedload(Curso.profesor).joinedload(Profesor.usuario)
    ).filter(Matricula.id_alumno == student_id).all()
    
    courses = []
    for m in matriculas:
        c = m.curso
        prof_name = f"{c.profesor.usuario.nombre} {c.profesor.usuario.apellidos or ''}".strip()
        
        progreso = db.query(Progreso).filter(Progreso.id_alumno == student_id, Progreso.id_curso == c.id_curso).first()
        prog_pct = float(progreso.porcentaje) if progreso else 0
        
        courses.append({
            "id": c.id_curso,
            "name": c.nombre,
            "description": c.descripcion,
            "teacher": prof_name,
            "progress": prog_pct
        })
    return courses

@router.get("/tasks")
def get_tasks(student: Alumno = Depends(get_current_student), db: Session = Depends(get_db)):
    student_id = student.id_alumno
    matriculas = db.query(Matricula).filter(Matricula.id_alumno == student_id).all()
    curso_ids = [m.id_curso for m in matriculas]
    
    if not curso_ids:
        return []
        
    actividades = db.query(Actividad).options(joinedload(Actividad.curso)).filter(Actividad.id_curso.in_(curso_ids)).all()
    
    tasks = []
    now = datetime.now(timezone.utc)
    for a in actividades:
        entrega = db.query(Entrega).options(joinedload(Entrega.calificacion)).filter(
            Entrega.id_actividad == a.id_actividad,
            Entrega.id_alumno == student_id
        ).first()
        
        status = "pending"
        score = None
        if entrega:
            status = "submitted"
            if entrega.calificacion:
                status = "graded"
                score = float(entrega.calificacion.nota)
        elif a.fecha_entrega and a.fecha_entrega.replace(tzinfo=timezone.utc) < now:
            status = "overdue"
            
        tasks.append({
            "id": a.id_actividad,
            "title": a.titulo,
            "course": a.curso.nombre,
            "due_date": a.fecha_entrega.isoformat() if a.fecha_entrega else None,
            "max_score": float(a.puntuacion_maxima),
            "status": status,
            "score": score
        })
    return tasks

@router.post("/tasks/{task_id}/submit")
def submit_task(task_id: int, payload: TaskSubmit, student: Alumno = Depends(get_current_student), db: Session = Depends(get_db)):
    student_id = student.id_alumno
    actividad = db.query(Actividad).filter(Actividad.id_actividad == task_id).first()
    if not actividad:
        raise HTTPException(status_code=404, detail="Tarea no encontrada")

    entrega = db.query(Entrega).filter(Entrega.id_actividad == task_id, Entrega.id_alumno == student_id).first()
    if entrega:
        entrega.contenido = payload.contenido
        entrega.estado = "entregado"
        entrega.fecha_entrega = datetime.now(timezone.utc)
    else:
        entrega = Entrega(
            id_actividad=task_id,
            id_alumno=student_id,
            contenido=payload.contenido,
            estado="entregado"
        )
        db.add(entrega)
    db.commit()
    return {"message": "Tarea entregada correctamente"}

@router.get("/grades")
def get_grades(student: Alumno = Depends(get_current_student), db: Session = Depends(get_db)):
    student_id = student.id_alumno
    entregas = db.query(Entrega).options(
        joinedload(Entrega.actividad).joinedload(Actividad.curso),
        joinedload(Entrega.calificacion)
    ).filter(Entrega.id_alumno == student_id).all()
    
    grades = []
    for e in entregas:
        if not e.calificacion:
            continue
            
        a = e.actividad
        grades.append({
            "task_id": a.id_actividad,
            "task_title": a.titulo,
            "course": a.curso.nombre,
            "score": float(e.calificacion.nota),
            "max_score": float(a.puntuacion_maxima),
            "feedback": e.calificacion.observaciones,
            "date": e.calificacion.fecha_calificacion.isoformat()
        })
    return grades

@router.get("/schedule")
def get_schedule(student: Alumno = Depends(get_current_student), db: Session = Depends(get_db)):
    student_id = student.id_alumno
    matriculas = db.query(Matricula).filter(Matricula.id_alumno == student_id).all()
    curso_ids = [m.id_curso for m in matriculas]
    if not curso_ids: return []
    horarios = db.query(Horario).options(joinedload(Horario.curso)).filter(Horario.id_curso.in_(curso_ids)).all()
    res = []
    for h in horarios:
        res.append({
            "day": h.dia_semana,
            "start": h.hora_inicio,
            "end": h.hora_fin,
            "course": h.curso.nombre,
            "room": h.aula
        })
    return res

@router.get("/projects")
def get_projects(student: Alumno = Depends(get_current_student), db: Session = Depends(get_db)):
    student_id = student.id_alumno
    pes = db.query(ProyectoEstudiante).options(joinedload(ProyectoEstudiante.proyecto).joinedload(Proyecto.curso)).filter(ProyectoEstudiante.id_alumno == student_id).all()
    res = []
    for pe in pes:
        p = pe.proyecto
        # Simulated teammates for UI purposes
        teammates = [{"name": "A", "initial": "A"}, {"name": "B", "initial": "B"}, {"name": "C", "initial": "C"}]
        res.append({
            "id": p.id_proyecto,
            "title": p.titulo,
            "description": p.descripcion,
            "course": p.curso.nombre,
            "due_date": p.fecha_entrega.isoformat() if p.fecha_entrega else None,
            "status": p.estado,
            "progress": float(p.porcentaje_completado),
            "team": teammates
        })
    return res

@router.post("/projects/{project_id}/progress")
def update_project_progress(project_id: int, payload: ProjectProgress, student: Alumno = Depends(get_current_student), db: Session = Depends(get_db)):
    student_id = student.id_alumno
    pe = db.query(ProyectoEstudiante).filter(ProyectoEstudiante.id_proyecto == project_id, ProyectoEstudiante.id_alumno == student_id).first()
    if not pe:
        raise HTTPException(status_code=403, detail="No eres parte de este proyecto")
        
    p = db.query(Proyecto).filter(Proyecto.id_proyecto == project_id).first()
    if p:
        p.porcentaje_completado = max(0, min(100, payload.progress))
        if p.porcentaje_completado == 100:
            p.estado = "entregado"
        else:
            p.estado = "en curso"
        db.commit()
    return {"message": "Progreso actualizado"}

@router.get("/exams")
def get_exams(student: Alumno = Depends(get_current_student), db: Session = Depends(get_db)):
    student_id = student.id_alumno
    matriculas = db.query(Matricula).filter(Matricula.id_alumno == student_id).all()
    curso_ids = [m.id_curso for m in matriculas]
    if not curso_ids: return []
    examenes = db.query(Examen).options(joinedload(Examen.curso)).filter(Examen.id_curso.in_(curso_ids)).all()
    res = []
    for e in examenes:
        res.append({
            "id": e.id_examen,
            "title": e.titulo,
            "syllabus": e.temario,
            "course": e.curso.nombre,
            "date": e.fecha.isoformat(),
            "duration": e.duracion_minutos,
            "mode": e.modalidad
        })
    return res
