"""Highlight detection admin endpoints.

Trigger scoring, list candidates, and view score breakdowns.
"""

from __future__ import annotations

import logging
from typing import Annotated

from fastapi import APIRouter, Depends, HTTPException, Query
from sqlalchemy import func, select
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy.orm import joinedload

from database import get_session
from models import HighlightCandidate, KeyMoment, ProcessingStatus, SourceVideo
from pipeline.highlight_schemas import HighlightCandidateResponse

logger = logging.getLogger("chrysopedia.highlights")

router = APIRouter(prefix="/admin/highlights", tags=["highlights"])


# ── Trigger endpoints ────────────────────────────────────────────────────────

@router.post("/detect/{video_id}")
async def detect_highlights(
    video_id: str,
    db: AsyncSession = Depends(get_session),
):
    """Dispatch highlight detection for a single video."""
    stmt = select(SourceVideo).where(SourceVideo.id == video_id)
    result = await db.execute(stmt)
    video = result.scalar_one_or_none()

    if video is None:
        raise HTTPException(status_code=404, detail=f"Video not found: {video_id}")

    from pipeline.stages import stage_highlight_detection

    try:
        task = stage_highlight_detection.delay(str(video.id))
        logger.info("Highlight detection dispatched for video_id=%s task_id=%s", video_id, task.id)
    except Exception as exc:
        logger.warning("Failed to dispatch highlight detection for video_id=%s: %s", video_id, exc)
        raise HTTPException(
            status_code=503,
            detail="Highlight detection dispatch failed — Celery/Redis may be unavailable",
        ) from exc

    return {
        "status": "dispatched",
        "video_id": str(video.id),
        "task_id": task.id,
    }


@router.post("/detect-all")
async def detect_all_highlights(
    db: AsyncSession = Depends(get_session),
):
    """Dispatch highlight detection for all completed videos."""
    stmt = (
        select(SourceVideo)
        .where(SourceVideo.processing_status == ProcessingStatus.complete)
    )
    result = await db.execute(stmt)
    videos = result.scalars().all()

    from pipeline.stages import stage_highlight_detection

    dispatched = 0
    errors = 0
    for video in videos:
        try:
            stage_highlight_detection.delay(str(video.id))
            dispatched += 1
        except Exception as exc:
            logger.warning(
                "Failed to dispatch highlight detection for video_id=%s: %s",
                video.id, exc,
            )
            errors += 1

    return {
        "status": "dispatched",
        "videos_dispatched": dispatched,
        "errors": errors,
    }


# ── Query endpoints ──────────────────────────────────────────────────────────

@router.get("/candidates", response_model=list[HighlightCandidateResponse])
async def list_candidates(
    db: AsyncSession = Depends(get_session),
    skip: Annotated[int, Query(ge=0)] = 0,
    limit: Annotated[int, Query(ge=1, le=200)] = 50,
):
    """List highlight candidates sorted by score descending, with pagination."""
    stmt = (
        select(HighlightCandidate)
        .options(joinedload(HighlightCandidate.key_moment))
        .order_by(HighlightCandidate.score.desc())
        .offset(skip)
        .limit(limit)
    )
    result = await db.execute(stmt)
    candidates = result.scalars().unique().all()
    return candidates


@router.get("/candidates/{candidate_id}", response_model=HighlightCandidateResponse)
async def get_candidate(
    candidate_id: str,
    db: AsyncSession = Depends(get_session),
):
    """Get a single highlight candidate by ID with full score breakdown."""
    stmt = (
        select(HighlightCandidate)
        .options(joinedload(HighlightCandidate.key_moment))
        .where(HighlightCandidate.id == candidate_id)
    )
    result = await db.execute(stmt)
    candidate = result.scalar_one_or_none()

    if candidate is None:
        raise HTTPException(status_code=404, detail=f"Candidate not found: {candidate_id}")

    return candidate
