"""tag.is_system + seed the three hygiene system tags

Training hygiene (operator 2026-07-03, milestone #128): rough WIPs tagged as a
character poison that character's head and CCIP references; banners/editor
screenshots pollute whole-image similarity. The fix keys on SYSTEM tags the
product ships — not operator configuration — so the seed lives here.

Seeding ADOPTS an existing same-(name, kind=general) tag (case-insensitive,
matching TagService.rename's collision stance) instead of inserting a
duplicate, so an operator who already tagged `wip` keeps their applications.

Revision ID: 0075
Revises: 0074
Create Date: 2026-07-03
"""
from typing import Sequence, Union

import sqlalchemy as sa
from alembic import op

revision: str = "0075"
down_revision: Union[str, None] = "0074"
branch_labels: Union[str, Sequence[str], None] = None
depends_on: Union[str, Sequence[str], None] = None

SYSTEM_TAG_NAMES = ("wip", "banner", "editor screenshot")


def upgrade() -> None:
    op.add_column(
        "tag",
        sa.Column(
            "is_system", sa.Boolean(), nullable=False,
            server_default=sa.false(),
        ),
    )
    conn = op.get_bind()
    for name in SYSTEM_TAG_NAMES:
        adopted = conn.execute(
            sa.text(
                "UPDATE tag SET is_system = true "
                "WHERE lower(name) = lower(:name) AND kind = 'general'"
            ),
            {"name": name},
        )
        if adopted.rowcount == 0:
            conn.execute(
                sa.text(
                    "INSERT INTO tag (name, kind, is_system) "
                    "VALUES (:name, 'general', true)"
                ),
                {"name": name},
            )


def downgrade() -> None:
    # The seeded rows survive as ordinary general tags — dropping the flag is
    # enough to disarm the mechanism, and deleting rows would orphan any
    # operator applications made while the flag existed.
    op.drop_column("tag", "is_system")
