"""Creator endpoints for Chrysopedia API.

Enhanced with sort (random default per R014), genre filter, and
technique/video counts for browse pages.
"""

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 database import get_session
from models import Creator, KeyMoment, SourceVideo, TechniquePage
from schemas import CreatorBrowseItem, CreatorDetail, CreatorRead, CreatorTechniqueItem

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

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


@router.get("")
async def list_creators(
    sort: Annotated[str, Query()] = "random",
    genre: Annotated[str | None, Query()] = None,
    offset: Annotated[int, Query(ge=0)] = 0,
    limit: Annotated[int, Query(ge=1, le=100)] = 50,
    db: AsyncSession = Depends(get_session),
):
    """List creators with sort, genre filter, and technique/video counts.

    - **sort**: ``random`` (default, R014 creator equity), ``alpha``, ``views``
    - **genre**: filter by genre (matches against ARRAY column)
    """
    # Subqueries for counts
    technique_count_sq = (
        select(func.count())
        .where(TechniquePage.creator_id == Creator.id)
        .correlate(Creator)
        .scalar_subquery()
    )
    video_count_sq = (
        select(func.count())
        .where(SourceVideo.creator_id == Creator.id)
        .correlate(Creator)
        .scalar_subquery()
    )
    last_technique_sq = (
        select(func.max(TechniquePage.created_at))
        .where(TechniquePage.creator_id == Creator.id)
        .correlate(Creator)
        .scalar_subquery()
    )

    stmt = select(
        Creator,
        technique_count_sq.label("technique_count"),
        video_count_sq.label("video_count"),
        last_technique_sq.label("last_technique_at"),
    ).where(Creator.hidden != True)  # noqa: E712

    # Genre filter
    if genre:
        stmt = stmt.where(Creator.genres.any(genre))

    # Sorting
    if sort == "alpha":
        stmt = stmt.order_by(Creator.name)
    elif sort == "views":
        stmt = stmt.order_by(Creator.view_count.desc())
    else:
        # Default: random (small dataset <100, func.random() is fine)
        stmt = stmt.order_by(func.random())

    stmt = stmt.offset(offset).limit(limit)
    result = await db.execute(stmt)
    rows = result.all()

    items: list[CreatorBrowseItem] = []
    for row in rows:
        creator = row[0]
        tc = row[1] or 0
        vc = row[2] or 0
        lta = row[3]  # None when creator has 0 techniques
        base = CreatorRead.model_validate(creator)
        items.append(
            CreatorBrowseItem(
                **base.model_dump(),
                technique_count=tc,
                video_count=vc,
                last_technique_at=lta,
            )
        )

    # Get total count (without offset/limit)
    count_stmt = select(func.count()).select_from(Creator).where(Creator.hidden != True)  # noqa: E712
    if genre:
        count_stmt = count_stmt.where(Creator.genres.any(genre))
    total = (await db.execute(count_stmt)).scalar() or 0

    logger.debug(
        "Listed %d creators (sort=%s, genre=%s, offset=%d, limit=%d)",
        len(items), sort, genre, offset, limit,
    )
    return {"items": items, "total": total, "offset": offset, "limit": limit}


@router.get("/{slug}", response_model=CreatorDetail)
async def get_creator(
    slug: str,
    db: AsyncSession = Depends(get_session),
) -> CreatorDetail:
    """Get a single creator by slug with full profile data.

    Returns video/technique counts, full technique list, genre breakdown,
    bio, social links, and avatar for the creator landing page.
    """
    stmt = select(Creator).where(Creator.slug == slug)
    result = await db.execute(stmt)
    creator = result.scalar_one_or_none()

    if creator is None:
        raise HTTPException(status_code=404, detail=f"Creator '{slug}' not found")

    # Video count
    video_count = (await db.execute(
        select(func.count()).select_from(SourceVideo)
        .where(SourceVideo.creator_id == creator.id)
    )).scalar() or 0

    # Moment count (key moments across all creator's videos)
    moment_count = (await db.execute(
        select(func.count()).select_from(KeyMoment)
        .join(SourceVideo, KeyMoment.source_video_id == SourceVideo.id)
        .where(SourceVideo.creator_id == creator.id)
    )).scalar() or 0

    # Technique pages for this creator
    key_moment_count_sq = (
        select(func.count(KeyMoment.id))
        .where(KeyMoment.technique_page_id == TechniquePage.id)
        .correlate(TechniquePage)
        .scalar_subquery()
        .label("key_moment_count")
    )
    technique_rows = (await db.execute(
        select(
            TechniquePage.title,
            TechniquePage.slug,
            TechniquePage.topic_category,
            TechniquePage.created_at,
            TechniquePage.summary,
            TechniquePage.topic_tags,
            key_moment_count_sq,
        )
        .where(TechniquePage.creator_id == creator.id)
        .order_by(TechniquePage.created_at.desc())
    )).all()

    techniques = [
        CreatorTechniqueItem(
            title=t.title, slug=t.slug,
            topic_category=t.topic_category, created_at=t.created_at,
            summary=t.summary, topic_tags=t.topic_tags,
            key_moment_count=t.key_moment_count,
        )
        for t in technique_rows
    ]

    # Genre breakdown across this creator's techniques
    genre_breakdown: dict[str, int] = {}
    for t in technique_rows:
        cat = t.topic_category
        genre_breakdown[cat] = genre_breakdown.get(cat, 0) + 1

    creator_data = CreatorRead.model_validate(creator)
    return CreatorDetail(
        **creator_data.model_dump(),
        bio=creator.bio,
        social_links=creator.social_links,
        featured=creator.featured,
        video_count=video_count,
        technique_count=len(techniques),
        techniques=techniques,
        genre_breakdown=genre_breakdown,
    )
