from fastapi import APIRouter, Depends, HTTPException, Query
from sqlalchemy import select
from typing import Optional

from app.core.deps import DB, CurrentUser, require_any_authenticated
from app.models.academic import Subject, Grade, SubjectGrade, Package, Topic, TopicLevel, Question, AnswerOption

router = APIRouter(
    prefix="/academic", tags=["Academic Content"], dependencies=[Depends(require_any_authenticated)]
)


@router.get("/subjects", summary="List All Subjects")
async def list_subjects(db: DB):
    result = await db.execute(
        select(Subject).where(Subject.is_active == True).order_by(Subject.name)
    )
    subjects = result.scalars().all()
    return [
        {
            "id": s.id,
            "name": s.name,
            "slug": s.slug,
            "description": s.description,
            "icon_url": s.icon_url,
            "color_hex": s.color_hex,
        }
        for s in subjects
    ]


@router.get("/subjects/{subject_id}", summary="Get Subject Details")
async def get_subject(subject_id: int, db: DB):
    result = await db.execute(select(Subject).where(Subject.id == subject_id))
    subject = result.scalar_one_or_none()
    if not subject:
        raise HTTPException(status_code=404, detail="Subject not found")
    return {
        "id": subject.id,
        "name": subject.name,
        "slug": subject.slug,
        "description": subject.description,
        "icon_url": subject.icon_url,
        "color_hex": subject.color_hex,
    }


@router.get("/grades", summary="List All Grades")
async def list_grades(db: DB):
    result = await db.execute(
        select(Grade).where(Grade.is_active == True).order_by(Grade.level_order)
    )
    grades = result.scalars().all()
    return [
        {
            "id": g.id,
            "name": g.name,
            "slug": g.slug,
            "description": g.description,
            "level_order": g.level_order,
        }
        for g in grades
    ]


@router.get("/grades/{grade_id}", summary="Get Grade Details")
async def get_grade(grade_id: int, db: DB):
    result = await db.execute(select(Grade).where(Grade.id == grade_id))
    grade = result.scalar_one_or_none()
    if not grade:
        raise HTTPException(status_code=404, detail="Grade not found")
    return {
        "id": grade.id,
        "name": grade.name,
        "slug": grade.slug,
        "description": grade.description,
        "level_order": grade.level_order,
    }


@router.get("/grades/{grade_id}/subjects", summary="Get Subjects for a Grade")
async def get_grade_subjects(grade_id: int, db: DB):
    result = await db.execute(
        select(Subject)
        .join(SubjectGrade, Subject.id == SubjectGrade.subject_id)
        .where(SubjectGrade.grade_id == grade_id, Subject.is_active == True)
    )
    subjects = result.scalars().all()
    return [
        {
            "id": s.id,
            "name": s.name,
            "slug": s.slug,
            "description": s.description,
            "icon_url": s.icon_url,
            "color_hex": s.color_hex,
        }
        for s in subjects
    ]


@router.get("/packages", summary="List Subscription Packages")
async def list_packages(db: DB):
    result = await db.execute(
        select(Package).where(Package.is_active == True).order_by(Package.price)
    )
    packages = result.scalars().all()
    return [
        {
            "id": p.id,
            "name": p.name,
            "slug": p.slug,
            "description": p.description,
            "price": str(p.price) if p.price else "0",
            "duration_days": p.duration_days,
            "is_active": p.is_active,
        }
        for p in packages
    ]


@router.get("/topics", summary="List Topics")
async def list_topics(
    db: DB,
    grade_id: Optional[int] = None,
    subject_id: Optional[int] = None,
    package_slug: Optional[str] = None,
):
    query = select(Topic).where(Topic.is_active == True)
    if grade_id or subject_id:
        query = query.join(SubjectGrade, Topic.subject_grade_id == SubjectGrade.id)
        if grade_id:
            query = query.where(SubjectGrade.grade_id == grade_id)
        if subject_id:
            query = query.where(SubjectGrade.subject_id == subject_id)
    if package_slug:
        query = query.join(Package, Topic.package_id == Package.id).where(Package.slug == package_slug)
    result = await db.execute(query.order_by(Topic.sequence_order))
    return result.scalars().all()


@router.get("/topics/{topic_id}", summary="Get Topic Details")
async def get_topic(topic_id: int, db: DB):
    result = await db.execute(select(Topic).where(Topic.id == topic_id))
    topic = result.scalar_one_or_none()
    if not topic:
        raise HTTPException(status_code=404, detail="Topic not found")
    return topic


@router.get("/topics/{topic_id}/levels", summary="Get Levels for a Topic")
async def get_topic_levels(topic_id: int, db: DB, current_user: CurrentUser):
    """
    Returns all levels for a topic with player progress included.
    Premium levels show as locked for freemium users.
    """
    from app.services.subscription_service import check_premium_access
    from app.models.progress import PlayerProgress

    access = await check_premium_access(db, current_user.id)

    # Get topic to check package
    topic_result = await db.execute(select(Topic).where(Topic.id == topic_id))
    topic = topic_result.scalar_one_or_none()
    if not topic:
        raise HTTPException(status_code=404, detail="Topic not found")

    pkg_result = await db.execute(select(Package).where(Package.id == topic.package_id))
    pkg = pkg_result.scalar_one_or_none()
    is_premium_topic = pkg and pkg.name == "premium"

    levels_result = await db.execute(
        select(TopicLevel)
        .where(TopicLevel.topic_id == topic_id, TopicLevel.is_active == True)
        .order_by(TopicLevel.level_number)
    )
    levels = levels_result.scalars().all()

    result = []
    for level in levels:
        # Get player's best progress
        progress_result = await db.execute(
            select(PlayerProgress).where(
                PlayerProgress.student_user_id == current_user.id,
                PlayerProgress.topic_level_id == level.id,
            )
        )
        progress = progress_result.scalar_one_or_none()

        # Determine if locked
        is_locked = is_premium_topic and not access["is_premium"]
        # Levels > 5 require completing level 5 first (for freemium topics)
        if not is_locked and level.level_number > 1:
            prev_progress = await db.execute(
                select(PlayerProgress).where(
                    PlayerProgress.student_user_id == current_user.id,
                    PlayerProgress.topic_level_id == level.id - 1,
                    PlayerProgress.is_completed == True,
                )
            )
            if not prev_progress.scalar_one_or_none() and level.level_number > 1:
                is_locked = True

        result.append({
            "id": level.id,
            "level_number": level.level_number,
            "level_name": level.level_name,
            "xp_reward": level.xp_reward,
            "stars_max": level.stars_max,
            "passing_score": level.passing_score,
            "is_locked": is_locked,
            "progress": {
                "best_score": progress.best_score if progress else 0,
                "best_stars": progress.best_stars if progress else 0,
                "is_completed": progress.is_completed if progress else False,
                "attempts_count": progress.attempts_count if progress else 0,
            } if progress else None,
        })
    return result


@router.get("/levels/{level_id}/questions", summary="Get Questions for a Level")
async def get_level_questions(level_id: int, db: DB, current_user: CurrentUser):
    """Get questions with answer options for a level. Does NOT reveal correct answers."""
    result = await db.execute(
        select(Question)
        .where(Question.level_id == level_id, Question.is_active == True)
        .order_by(Question.display_order)
    )
    questions = result.scalars().all()

    output = []
    for q in questions:
        answers_result = await db.execute(
            select(AnswerOption)
            .where(AnswerOption.question_id == q.id, AnswerOption.is_active == True)
            .order_by(AnswerOption.display_order)
        )
        answers = answers_result.scalars().all()
        output.append({
            "id": q.id,
            "question_text": q.question_text,
            "question_type": q.question_type,
            "asset_2d_url": q.asset_2d_url,
            "audio_url": q.audio_url,
            "hint_text": q.hint_text,
            "time_limit_seconds": q.time_limit_seconds,
            "points": q.points,
            "answers": [
                {
                    "id": a.id,
                    "answer_text": a.answer_text,
                    "asset_2d_url": a.asset_2d_url,
                    "display_order": a.display_order,
                    "monetary_value": a.monetary_value,
                }
                for a in answers
            ],
        })
    return output
