"""Blacklists — globalnie ukryte performerki/studia/tagi.

Sceny które MAJĄ blacklisted entity wypadają z każdego /scenes (pełna lista, search,
performer scenes, tag scenes). Auto-apply w `app/api/scenes.py`.

Endpointy:
  GET    /blacklist                            — wszystkie 3 listy w jednym response
  POST   /blacklist/{kind}/{entity_id}         — dodaj (idempotent)
  DELETE /blacklist/{kind}/{entity_id}         — usuń

`kind` ∈ {performer, studio, tag}.
"""
from __future__ import annotations

import uuid
from typing import Annotated, Literal

from fastapi import APIRouter, Depends, HTTPException, status
from pydantic import BaseModel
from sqlalchemy import select
from sqlalchemy.orm import Session

from app.api.device import get_device_id
from app.auth import require_api_key
from app.db import get_session
from app.models.blacklist import (
    BlacklistedPerformer,
    BlacklistedStudio,
    BlacklistedTag,
)
from app.models.performer import Performer
from app.models.studio import Studio
from app.models.tag import Tag

router = APIRouter(
    prefix="/blacklist", tags=["blacklist"], dependencies=[Depends(require_api_key)]
)

Kind = Literal["performer", "studio", "tag"]


class BlacklistEntry(BaseModel):
    id: uuid.UUID
    name: str  # canonical_name (performer) / name (studio/tag)
    slug: str | None = None


class BlacklistOut(BaseModel):
    performers: list[BlacklistEntry]
    studios: list[BlacklistEntry]
    tags: list[BlacklistEntry]


@router.get("", response_model=BlacklistOut)
def list_blacklist(
    session: Annotated[Session, Depends(get_session)],
    device_id: Annotated[str, Depends(get_device_id)],
) -> BlacklistOut:
    perfs = session.execute(
        select(BlacklistedPerformer.performer_id, Performer.canonical_name, Performer.slug)
        .join(Performer, Performer.id == BlacklistedPerformer.performer_id)
        .where(BlacklistedPerformer.device_id == device_id)
        .order_by(Performer.canonical_name)
    ).all()
    studios = session.execute(
        select(BlacklistedStudio.studio_id, Studio.name, Studio.slug)
        .join(Studio, Studio.id == BlacklistedStudio.studio_id)
        .where(BlacklistedStudio.device_id == device_id)
        .order_by(Studio.name)
    ).all()
    tags = session.execute(
        select(BlacklistedTag.tag_id, Tag.name, Tag.slug)
        .join(Tag, Tag.id == BlacklistedTag.tag_id)
        .where(BlacklistedTag.device_id == device_id)
        .order_by(Tag.name)
    ).all()
    return BlacklistOut(
        performers=[BlacklistEntry(id=r[0], name=r[1], slug=r[2]) for r in perfs],
        studios=[BlacklistEntry(id=r[0], name=r[1], slug=r[2]) for r in studios],
        tags=[BlacklistEntry(id=r[0], name=r[1], slug=r[2]) for r in tags],
    )


def _kind_to_entity(kind: Kind):
    if kind == "performer":
        return BlacklistedPerformer, Performer, "performer_id"
    if kind == "studio":
        return BlacklistedStudio, Studio, "studio_id"
    if kind == "tag":
        return BlacklistedTag, Tag, "tag_id"
    raise HTTPException(status_code=400, detail="kind must be performer|studio|tag")


@router.post("/{kind}/{entity_id}", status_code=status.HTTP_200_OK)
def add_blacklist(
    kind: Kind,
    entity_id: uuid.UUID,
    session: Annotated[Session, Depends(get_session)],
    device_id: Annotated[str, Depends(get_device_id)],
) -> dict:
    bl_model, parent_model, fk = _kind_to_entity(kind)
    if session.get(parent_model, entity_id) is None:
        raise HTTPException(status_code=404, detail=f"{kind} not found")
    if session.get(bl_model, (device_id, entity_id)) is not None:
        return {"kind": kind, "id": str(entity_id), "created": False}
    session.add(bl_model(**{"device_id": device_id, fk: entity_id}))
    session.commit()
    return {"kind": kind, "id": str(entity_id), "created": True}


@router.delete("/{kind}/{entity_id}", status_code=status.HTTP_204_NO_CONTENT)
def remove_blacklist(
    kind: Kind,
    entity_id: uuid.UUID,
    session: Annotated[Session, Depends(get_session)],
    device_id: Annotated[str, Depends(get_device_id)],
) -> None:
    bl_model, _, _ = _kind_to_entity(kind)
    row = session.get(bl_model, (device_id, entity_id))
    if row is None:
        return  # idempotent
    session.delete(row)
    session.commit()
