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

from app.database import get_db
from app.dependencies import require_user_token
from app.models import User
from app.programme.models_programme import normalize_programme_level_slug
from app.programme.services.programme_service import serialize_programme_catalog
from app.schemas import (
    ProgrammeCatalogResponse,
    ProgrammeTrackResponse,
    TrackCompleteRequest,
    UserTrackTraceListResponse,
)
from app.services.user_register_step_service import reseed_track_from_register_step
from app.services.user_track_service import complete_track_item, get_programme_track, list_user_track_traces

router = APIRouter(tags=["user-programme"])


def _parse_level_slug(level: str | None) -> str | None:
    if level is None or not level.strip():
        return None
    try:
        return normalize_programme_level_slug(level)
    except ValueError as e:
        raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=str(e)) from e


@router.get(
    "/programme/catalog",
    response_model=ProgrammeCatalogResponse,
    summary="Get programme hierarchy for the user frontend",
)
def get_programme_catalog(
    level: str | None = Query(
        None,
        description="Optional level slug filter (any admin-created level)",
    ),
    db: Session = Depends(get_db),
    _: User = Depends(require_user_token),
):
    return serialize_programme_catalog(db, level_slug=_parse_level_slug(level))


@router.get(
    "/programme/track",
    response_model=ProgrammeTrackResponse,
    summary="Get programme track with open/locked/completed items for the user UI",
)
def get_track(
    level: str | None = Query(
        None,
        description="Optional level slug filter (any admin-created level)",
    ),
    module_kind: str | None = Query(
        None,
        description="Optional module kind filter (any admin-created module type)",
    ),
    db: Session = Depends(get_db),
    user: User = Depends(require_user_token),
):
    return get_programme_track(db, user, level=level, module_kind=module_kind)


@router.post(
    "/programme/track/reseed",
    response_model=ProgrammeTrackResponse,
    summary="Re-apply auto-done progress from registration anchor",
)
def reseed_track(
    level: str | None = Query(None),
    module_kind: str | None = Query(None),
    db: Session = Depends(get_db),
    user: User = Depends(require_user_token),
):
    reseed_track_from_register_step(db, user)
    db.commit()
    return get_programme_track(db, user, level=level, module_kind=module_kind)


@router.post(
    "/programme/track/complete",
    response_model=ProgrammeTrackResponse,
    summary="Mark the currently open assessment or session as completed",
)
def complete_track(
    body: TrackCompleteRequest,
    db: Session = Depends(get_db),
    user: User = Depends(require_user_token),
):
    return complete_track_item(db, user, body)


@router.get(
    "/programme/track/traces",
    response_model=UserTrackTraceListResponse,
    summary="List saved track clicks (user_track_traces table) for dashboard",
)
def list_track_traces(
    limit: int = Query(100, ge=1, le=500),
    db: Session = Depends(get_db),
    user: User = Depends(require_user_token),
):
    rows = list_user_track_traces(db, user.id, limit=limit)
    return UserTrackTraceListResponse(total=len(rows), traces=rows)
