"""
Migrazione 0017: Tassonomia di Classificazione Multi-livello (Feature N2).

Estende la tabella `labels` con:
  - parent_id: FK self-referenziale (nullable) per struttura ad albero
  - description: testo descrittivo opzionale

Struttura tassonomica:
  Livello 0 (radice) = Ambito (Area Aziendale)  — parent_id IS NULL
  Livello 1          = Processo                  — parent_id = ID Ambito
  Livello 2 (foglia) = Classificazione           — parent_id = ID Processo

I vincoli di unicità vengono sostituiti con indici parziali per supportare
nomi identici a diversi livelli dell'albero.
"""

from alembic import op
import sqlalchemy as sa
from sqlalchemy.dialects import postgresql

revision = "0017"
down_revision = "0016"
branch_labels = None
depends_on = None


def upgrade() -> None:
    # ── Aggiunge parent_id (FK self-referenziale nullable) ─────────────────────
    op.add_column(
        "labels",
        sa.Column(
            "parent_id",
            postgresql.UUID(as_uuid=True),
            nullable=True,
        ),
    )
    op.create_foreign_key(
        "fk_labels_parent",
        "labels",
        "labels",
        ["parent_id"],
        ["id"],
        ondelete="CASCADE",
    )

    # ── Aggiunge description ────────────────────────────────────────────────────
    op.add_column(
        "labels",
        sa.Column("description", sa.Text(), nullable=True),
    )

    # ── Indice su parent_id per query gerarchiche ───────────────────────────────
    op.create_index("idx_labels_parent", "labels", ["parent_id"])

    # ── Sostituisce il vincolo di unicità con indici parziali ───────────────────
    # Il vecchio vincolo (tenant_id, name) non supporta nomi uguali a livelli diversi
    op.drop_constraint("uq_label_name_tenant", "labels")

    # Nodi radice: nome unico per tenant (parent_id IS NULL)
    op.execute(
        "CREATE UNIQUE INDEX uq_label_name_root "
        "ON labels (tenant_id, name) WHERE parent_id IS NULL"
    )
    # Nodi non-radice: nome unico per (tenant, parent) — stesso nome ammesso sotto parent diversi
    op.execute(
        "CREATE UNIQUE INDEX uq_label_name_parent "
        "ON labels (tenant_id, name, parent_id) WHERE parent_id IS NOT NULL"
    )


def downgrade() -> None:
    op.execute("DROP INDEX IF EXISTS uq_label_name_parent")
    op.execute("DROP INDEX IF EXISTS uq_label_name_root")
    op.create_unique_constraint("uq_label_name_tenant", "labels", ["tenant_id", "name"])
    op.drop_index("idx_labels_parent", table_name="labels")
    op.drop_constraint("fk_labels_parent", "labels", type_="foreignkey")
    op.drop_column("labels", "description")
    op.drop_column("labels", "parent_id")
