"""Follow system — users follow creators.

Endpoints:
  POST   /follows/{creator_id}        — follow a creator
  DELETE /follows/{creator_id}        — unfollow a creator
  GET    /follows/{creator_id}/status — check if following
  GET    /follows/me                  — list followed creators
"""

from __future__ import annotations

import uuid
from typing import Annotated

from fastapi import APIRouter, Depends, HTTPException, status
from sqlalchemy import delete, func, select
from sqlalchemy.dialects.postgresql import insert as pg_insert
from sqlalchemy.ext.asyncio import AsyncSession

from auth import get_current_user
from database import get_session
from models import Creator, CreatorFollow, User
from schemas import FollowResponse, FollowStatusResponse, FollowedCreatorItem

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


async def _follower_count(session: AsyncSession, creator_id: uuid.UUID) -> int:
    result = await session.execute(
        select(func.count()).select_from(CreatorFollow).where(
            CreatorFollow.creator_id == creator_id
        )
    )
    return result.scalar_one()


@router.post("/{creator_id}", response_model=FollowResponse)
async def follow_creator(
    creator_id: uuid.UUID,
    current_user: Annotated[User, Depends(get_current_user)],
    session: Annotated[AsyncSession, Depends(get_session)],
):
    """Follow a creator. Idempotent — following twice is a no-op."""
    # Verify creator exists
    result = await session.execute(select(Creator).where(Creator.id == creator_id))
    if result.scalar_one_or_none() is None:
        raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Creator not found")

    # Upsert — idempotent
    stmt = pg_insert(CreatorFollow).values(
        user_id=current_user.id,
        creator_id=creator_id,
    ).on_conflict_do_nothing(constraint="uq_creator_follow_user_creator")
    await session.execute(stmt)
    await session.commit()

    count = await _follower_count(session, creator_id)
    return FollowResponse(followed=True, creator_id=creator_id, follower_count=count)


@router.delete("/{creator_id}", response_model=FollowResponse)
async def unfollow_creator(
    creator_id: uuid.UUID,
    current_user: Annotated[User, Depends(get_current_user)],
    session: Annotated[AsyncSession, Depends(get_session)],
):
    """Unfollow a creator. Idempotent — unfollowing when not following is a no-op."""
    await session.execute(
        delete(CreatorFollow).where(
            CreatorFollow.user_id == current_user.id,
            CreatorFollow.creator_id == creator_id,
        )
    )
    await session.commit()

    count = await _follower_count(session, creator_id)
    return FollowResponse(followed=False, creator_id=creator_id, follower_count=count)


@router.get("/me", response_model=list[FollowedCreatorItem])
async def my_follows(
    current_user: Annotated[User, Depends(get_current_user)],
    session: Annotated[AsyncSession, Depends(get_session)],
):
    """List all creators the current user follows."""
    result = await session.execute(
        select(
            CreatorFollow.creator_id,
            Creator.name.label("creator_name"),
            Creator.slug.label("creator_slug"),
            CreatorFollow.created_at.label("followed_at"),
        )
        .join(Creator, CreatorFollow.creator_id == Creator.id)
        .where(CreatorFollow.user_id == current_user.id)
        .order_by(CreatorFollow.created_at.desc())
    )
    return [FollowedCreatorItem(**row._mapping) for row in result.all()]


@router.get("/{creator_id}/status", response_model=FollowStatusResponse)
async def follow_status(
    creator_id: uuid.UUID,
    current_user: Annotated[User, Depends(get_current_user)],
    session: Annotated[AsyncSession, Depends(get_session)],
):
    """Check if the current user follows a specific creator."""
    result = await session.execute(
        select(CreatorFollow.id).where(
            CreatorFollow.user_id == current_user.id,
            CreatorFollow.creator_id == creator_id,
        )
    )
    return FollowStatusResponse(
        following=result.scalar_one_or_none() is not None,
        creator_id=creator_id,
    )
