"""add workstream planning metadata and typed dependency targets

Revision ID: s6n7o8p9q0r1
Revises: r5m6n7o8p9q0
Create Date: 2026-05-04

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

revision = "s6n7o8p9q0r1"
down_revision = "r5m6n7o8p9q0"
branch_labels = None
depends_on = None


def upgrade() -> None:
    op.add_column("workstreams", sa.Column("planning_priority", sa.String(length=20), nullable=True))
    op.add_column("workstreams", sa.Column("planning_order", sa.Integer(), nullable=True))
    op.create_index("ix_workstreams_planning_priority", "workstreams", ["planning_priority"])
    op.create_index("ix_workstreams_planning_order", "workstreams", ["planning_order"])

    op.drop_constraint("uq_ws_dep_pair", "workstream_dependencies", type_="unique")
    op.add_column("workstream_dependencies", sa.Column("to_task_id", UUID(as_uuid=True), nullable=True))
    op.add_column(
        "workstream_dependencies",
        sa.Column("relationship_type", sa.String(length=40), nullable=False, server_default="blocks"),
    )
    op.alter_column(
        "workstream_dependencies",
        "to_workstream_id",
        existing_type=UUID(as_uuid=True),
        nullable=True,
    )
    op.create_foreign_key(
        "fk_ws_dep_to_task_id",
        "workstream_dependencies",
        "tasks",
        ["to_task_id"],
        ["id"],
        ondelete="CASCADE",
    )
    op.create_index("ix_workstream_dependencies_to_task_id", "workstream_dependencies", ["to_task_id"])
    op.create_index(
        "ix_workstream_dependencies_relationship_type",
        "workstream_dependencies",
        ["relationship_type"],
    )
    op.create_check_constraint(
        "ck_ws_dep_exactly_one_target",
        "workstream_dependencies",
        "(to_workstream_id IS NOT NULL AND to_task_id IS NULL) "
        "OR (to_workstream_id IS NULL AND to_task_id IS NOT NULL)",
    )
    op.create_index(
        "uq_ws_dep_workstream_target",
        "workstream_dependencies",
        ["from_workstream_id", "to_workstream_id", "relationship_type"],
        unique=True,
        postgresql_where=sa.text("to_workstream_id IS NOT NULL"),
    )
    op.create_index(
        "uq_ws_dep_task_target",
        "workstream_dependencies",
        ["from_workstream_id", "to_task_id", "relationship_type"],
        unique=True,
        postgresql_where=sa.text("to_task_id IS NOT NULL"),
    )


def downgrade() -> None:
    op.drop_index("uq_ws_dep_task_target", table_name="workstream_dependencies")
    op.drop_index("uq_ws_dep_workstream_target", table_name="workstream_dependencies")
    op.drop_constraint("ck_ws_dep_exactly_one_target", "workstream_dependencies", type_="check")
    op.drop_index("ix_workstream_dependencies_relationship_type", table_name="workstream_dependencies")
    op.drop_index("ix_workstream_dependencies_to_task_id", table_name="workstream_dependencies")
    op.drop_constraint("fk_ws_dep_to_task_id", "workstream_dependencies", type_="foreignkey")
    op.alter_column(
        "workstream_dependencies",
        "to_workstream_id",
        existing_type=UUID(as_uuid=True),
        nullable=False,
    )
    op.drop_column("workstream_dependencies", "relationship_type")
    op.drop_column("workstream_dependencies", "to_task_id")
    op.create_unique_constraint(
        "uq_ws_dep_pair",
        "workstream_dependencies",
        ["from_workstream_id", "to_workstream_id"],
    )

    op.drop_index("ix_workstreams_planning_order", table_name="workstreams")
    op.drop_index("ix_workstreams_planning_priority", table_name="workstreams")
    op.drop_column("workstreams", "planning_order")
    op.drop_column("workstreams", "planning_priority")
