"""taxonomy scene_count denormalization — tags / performers / studios

Revision ID: 0019_taxonomy_scene_counts
Revises: 0018_movie_play_progress
Create Date: 2026-05-31

Perf fix (user-report 2026-05-31 "wolne ładowanie scen/favorites/tags"): baza urosła
do 1.69M scen / 6.3M scene_tags, a /tags?order=popular liczył scene_count dla KAŻDEGO
tagu na żywo (agregacja 6.3M scene_tags + EXISTS playback, external-merge sort 22MB) —
~4.3s, i to razy 2 (total + items). Analogicznie performers/studios + favorites.

Denormalizujemy `scene_count` na tags/performers/studios. Worker przelicza je w tle
(`_job_refresh_taxonomy_counts`, co `GOON_SCHED_TAXONOMY_COUNTS_HOURS`=3h jednym
UPDATE...FROM). Endpointy czytają gotową kolumnę + ORDER BY indexed DESC → <20ms.

scene_count = liczba scen z danym tagiem/performerem/studiem mających ≥1 ŻYWY
playback_source (dead_at IS NULL) — dokładnie ta sama definicja co dotychczasowe
live-aggregaty (has_live_playback filter w taxonomies.py / favorites.py).

Counts są do ~3h nieświeże — dla "(123)" przy filtrze i sortu "popular" bez znaczenia.
"""
from collections.abc import Sequence

import sqlalchemy as sa
from alembic import op

revision: str = "0019_taxonomy_scene_counts"
down_revision: str | None = "0018_movie_play_progress"
branch_labels: str | Sequence[str] | None = None
depends_on: str | Sequence[str] | None = None

_TABLES = ("tags", "performers", "studios")


def upgrade() -> None:
    for tbl in _TABLES:
        op.add_column(
            tbl,
            sa.Column(
                "scene_count", sa.Integer(), nullable=False, server_default="0"
            ),
        )
        # DESC index — ORDER BY scene_count DESC (sortowanie "popular").
        op.create_index(
            f"ix_{tbl}_scene_count",
            tbl,
            [sa.text("scene_count DESC")],
        )


def downgrade() -> None:
    for tbl in _TABLES:
        op.drop_index(f"ix_{tbl}_scene_count", table_name=tbl)
        op.drop_column(tbl, "scene_count")
