"""Creator dashboard endpoint — authenticated analytics for a linked creator.

Returns aggregate counts (videos, technique pages, key moments, search
impressions) and content lists for the logged-in creator's dashboard.
"""

import logging
from typing import Annotated

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

from auth import get_current_user
from database import get_session
from models import (
    Creator,
    KeyMoment,
    SearchLog,
    SourceVideo,
    TechniquePage,
    User,
)
from schemas import (
    CreatorDashboardResponse,
    CreatorDashboardTechnique,
    CreatorDashboardVideo,
)

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

router = APIRouter(prefix="/creator", tags=["creator-dashboard"])


@router.get("/dashboard", response_model=CreatorDashboardResponse)
async def get_creator_dashboard(
    current_user: Annotated[User, Depends(get_current_user)],
    db: AsyncSession = Depends(get_session),
) -> CreatorDashboardResponse:
    """Return dashboard analytics for the authenticated creator.

    Requires the user to have a linked creator_id. Returns 404 if the
    user has no linked creator profile.
    """
    if current_user.creator_id is None:
        raise HTTPException(
            status_code=404,
            detail="No creator profile linked to this account",
        )

    creator_id = current_user.creator_id

    # Verify creator exists (defensive — FK should guarantee this)
    creator = (await db.execute(
        select(Creator).where(Creator.id == creator_id)
    )).scalar_one_or_none()
    if creator is None:
        logger.error("User %s has creator_id %s but creator row missing", current_user.id, creator_id)
        raise HTTPException(
            status_code=404,
            detail="Linked creator profile not found",
        )

    # ── Aggregate counts ─────────────────────────────────────────────────

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

    technique_count = (await db.execute(
        select(func.count()).select_from(TechniquePage)
        .where(TechniquePage.creator_id == creator_id)
    )).scalar() or 0

    key_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

    # Search impressions: count distinct search_log rows where the query
    # exactly matches (case-insensitive) any of this creator's technique titles.
    search_impressions = (await db.execute(
        select(func.count(func.distinct(SearchLog.id)))
        .where(
            select(TechniquePage.id)
            .where(
                TechniquePage.creator_id == creator_id,
                func.lower(SearchLog.query) == func.lower(TechniquePage.title),
            )
            .correlate(SearchLog)
            .exists()
        )
    )).scalar() or 0

    # ── Content lists ────────────────────────────────────────────────────

    # Techniques with per-page key moment count
    km_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,
            km_count_sq,
        )
        .where(TechniquePage.creator_id == creator_id)
        .order_by(TechniquePage.created_at.desc())
    )).all()

    techniques = [
        CreatorDashboardTechnique(
            title=r.title,
            slug=r.slug,
            topic_category=r.topic_category,
            created_at=r.created_at,
            key_moment_count=r.key_moment_count or 0,
        )
        for r in technique_rows
    ]

    # Videos
    video_rows = (await db.execute(
        select(
            SourceVideo.filename,
            SourceVideo.processing_status,
            SourceVideo.created_at,
        )
        .where(SourceVideo.creator_id == creator_id)
        .order_by(SourceVideo.created_at.desc())
    )).all()

    videos = [
        CreatorDashboardVideo(
            filename=r.filename,
            processing_status=r.processing_status.value if hasattr(r.processing_status, 'value') else str(r.processing_status),
            created_at=r.created_at,
        )
        for r in video_rows
    ]

    logger.info(
        "Dashboard loaded for creator %s: %d videos, %d techniques, %d moments, %d impressions",
        creator_id, video_count, technique_count, key_moment_count, search_impressions,
    )

    return CreatorDashboardResponse(
        video_count=video_count,
        technique_count=technique_count,
        key_moment_count=key_moment_count,
        search_impressions=search_impressions,
        techniques=techniques,
        videos=videos,
    )
