from fastapi import APIRouter, Depends, HTTPException, Query
from sqlalchemy import select, func
from sqlalchemy.orm import selectinload
from typing import Optional

from app.core.deps import DB, CurrentUser, require_student
from app.models.user import User, StudentProfile, ParentStudentLink
from app.models.school import School, SchoolStudentEnrollment
from app.models.progress import PlayerProgress, Award, PlayerAward, AcademicProgressSummary
from app.models.academic import Subject, Grade
from app.schemas.user import StudentDetailOut, StudentUpdateRequest, TransferSchoolRequest

router = APIRouter(
    prefix="/students", tags=["Students"], dependencies=[Depends(require_student)]
)


@router.get("/profile", summary="Get My Student Profile")
async def get_student_profile(current_user: CurrentUser, db: DB):
    """Returns the student's full profile with grade and school info."""
    result = await db.execute(
        select(StudentProfile).where(StudentProfile.user_id == current_user.id)
    )
    profile = result.scalar_one_or_none()
    if not profile:
        raise HTTPException(status_code=404, detail="Student profile not found")
    return {
        "user": {
            "id": current_user.id,
            "stem_id": current_user.stem_id,
            "email": current_user.email,
            "full_name": current_user.full_name,
            "first_name": current_user.first_name,
            "last_name": current_user.last_name,
            "role": current_user.role,
        },
        "profile": {
            "user_id": profile.user_id,
            "current_grade_id": profile.current_grade_id,
            "current_school_id": profile.current_school_id,
            "total_xp": profile.total_xp,
            "level_rank": profile.level_rank,
            "streak_days": profile.streak_days,
            "bio": profile.bio,
            "learning_style": profile.learning_style,
            "last_activity_at": profile.last_activity_at,
        },
    }


@router.patch("/profile", summary="Update My Student Profile")
async def update_profile(data: StudentUpdateRequest, current_user: CurrentUser, db: DB):
    """Update student profile (name, avatar, etc)."""
    for field, value in data.model_dump(exclude_none=True).items():
        if hasattr(current_user, field):
            setattr(current_user, field, value)
    await db.commit()
    return {"message": "Profile updated successfully"}


@router.get("/progress", summary="Get My Learning Progress")
async def get_my_progress(
    current_user: CurrentUser,
    db: DB,
    subject_id: Optional[int] = None,
):
    """Get the student's progress across all topics and levels."""
    query = select(PlayerProgress).where(PlayerProgress.student_user_id == current_user.id)
    result = await db.execute(query)
    progress_list = result.scalars().all()
    return progress_list


@router.get("/progress/summary", summary="Get Academic Progress Summary")
async def get_progress_summary(current_user: CurrentUser, db: DB):
    """Aggregated progress by subject and grade."""
    result = await db.execute(
        select(AcademicProgressSummary)
        .where(AcademicProgressSummary.student_user_id == current_user.id)
        .order_by(AcademicProgressSummary.last_activity_date.desc())
    )
    summaries = result.scalars().all()
    return [
        {
            "subject_id": s.subject_id,
            "grade_id": s.grade_id,
            "topics_attempted": s.topics_attempted,
            "topics_completed": s.topics_completed,
            "levels_completed": s.levels_completed,
            "average_score": str(s.average_score) if s.average_score else "0",
            "total_xp": s.total_xp,
            "last_activity_at": s.last_activity_date.isoformat() if s.last_activity_date else None,
        }
        for s in summaries
    ]


@router.get("/awards", summary="Get My Awards")
async def get_my_awards(current_user: CurrentUser, db: DB):
    """Get the student's earned awards and badges."""
    result = await db.execute(
        select(PlayerAward, Award)
        .join(Award, PlayerAward.award_id == Award.id)
        .where(PlayerAward.student_user_id == current_user.id)
        .order_by(PlayerAward.earned_at.desc())
    )
    rows = result.all()
    return [
        {
            "award": row.Award,
            "earned_at": row.PlayerAward.earned_at,
            "times_earned": row.PlayerAward.times_earned,
        }
        for row in rows
    ]


@router.get("/leaderboard", summary="Get Leaderboard for My Grade")
async def get_leaderboard(current_user: CurrentUser, db: DB):
    """Get the top students in the same grade."""
    profile_result = await db.execute(
        select(StudentProfile).where(StudentProfile.user_id == current_user.id)
    )
    profile = profile_result.scalar_one_or_none()
    if not profile or not profile.current_grade_id:
        return []

    result = await db.execute(
        select(User, StudentProfile)
        .join(StudentProfile, User.id == StudentProfile.user_id)
        .where(
            StudentProfile.current_grade_id == profile.current_grade_id,
            User.is_active == True,
        )
        .order_by(StudentProfile.total_xp.desc())
        .limit(50)
    )
    rows = result.all()
    return [
        {
            "rank": i + 1,
            "stem_id": row.User.stem_id,
            "full_name": row.User.full_name,
            "total_xp": row.StudentProfile.total_xp,
            "level_rank": row.StudentProfile.level_rank,
            "streak_days": row.StudentProfile.streak_days,
            "is_me": row.User.id == current_user.id,
        }
        for i, row in enumerate(rows)
    ]


@router.get("/school", summary="Get My School Enrollment")
async def get_my_school(current_user: CurrentUser, db: DB):
    """Get the student's current school enrollment."""
    result = await db.execute(
        select(SchoolStudentEnrollment, School)
        .join(School, SchoolStudentEnrollment.school_id == School.id)
        .where(
            SchoolStudentEnrollment.student_user_id == current_user.id,
            SchoolStudentEnrollment.is_active == True,
        )
    )
    row = result.first()
    if not row:
        return {"enrolled": False}

    return {
        "enrolled": True,
        "school_name": row.School.school_name,
        "school_code": row.School.school_code,
        "enrollment_date": row.SchoolStudentEnrollment.enrollment_date,
        "grade_at_enrollment": row.SchoolStudentEnrollment.grade_at_enrollment,
    }


@router.post("/enroll/{school_code}", summary="Enroll in a School via School Code")
async def enroll_in_school(school_code: str, current_user: CurrentUser, db: DB):
    """Enroll in a school using the school's access code."""
    result = await db.execute(select(School).where(
        School.access_code == school_code, School.is_verified == True
    ))
    school = result.scalar_one_or_none()
    if not school:
        raise HTTPException(status_code=404, detail="Invalid school code or school not verified")

    # Check not already enrolled
    existing = await db.execute(
        select(SchoolStudentEnrollment).where(
            SchoolStudentEnrollment.student_user_id == current_user.id,
            SchoolStudentEnrollment.school_id == school.id,
            SchoolStudentEnrollment.is_active == True,
        )
    )
    if existing.scalar_one_or_none():
        raise HTTPException(status_code=400, detail="Already enrolled in this school")

    from datetime import date
    enrollment = SchoolStudentEnrollment(
        school_id=school.id,
        student_user_id=current_user.id,
        enrollment_date=date.today(),
    )
    db.add(enrollment)
    await db.commit()
    return {"message": f"Successfully enrolled in {school.school_name}"}


@router.post("/transfer-school", summary="Request School Transfer")
async def transfer_school(data: TransferSchoolRequest, current_user: CurrentUser, db: DB):
    """Transfer student enrollment from one school to another via stem_id."""
    result = await db.execute(select(School).where(School.access_code == data.new_school_code))
    new_school = result.scalar_one_or_none()
    if not new_school or not new_school.is_verified:
        raise HTTPException(status_code=404, detail="Invalid school code")

    # Deactivate old enrollment
    old_enrollment = await db.execute(
        select(SchoolStudentEnrollment).where(
            SchoolStudentEnrollment.student_user_id == current_user.id,
            SchoolStudentEnrollment.is_active == True,
        )
    )
    old = old_enrollment.scalar_one_or_none()
    if old:
        from datetime import date
        old.is_active = False
        old.withdrawal_date = date.today()
        old.withdrawal_reason = data.reason

    from datetime import date
    enrollment = SchoolStudentEnrollment(
        school_id=new_school.id,
        student_user_id=current_user.id,
        enrollment_date=date.today(),
    )
    db.add(enrollment)
    await db.commit()
    return {"message": f"Transferred to {new_school.school_name} successfully. Your STEM ID remains the same."}


@router.get("/notifications", summary="Get My Notifications")
async def get_notifications(
    current_user: CurrentUser,
    db: DB,
    unread_only: bool = False,
):
    from app.models.user import Notification
    query = select(Notification).where(Notification.user_id == current_user.id)
    if unread_only:
        query = query.where(Notification.is_read == False)
    result = await db.execute(query.order_by(Notification.created_at.desc()).limit(50))
    return result.scalars().all()
