"""Add Business Unit and Client Branch scope to client related persons.

This migration is intentionally defensive. It adds only columns, foreign keys,
and indexes that are missing, so it is safe for databases where part of the
change may already exist.
"""

from alembic import op
import sqlalchemy as sa


revision = "20260806_related_person_scope"
down_revision = "20260805_scope_aware_services"
branch_labels = None
depends_on = None


TABLE_NAME = "client_related_persons"


def _column_names(inspector) -> set[str]:
    return {column["name"] for column in inspector.get_columns(TABLE_NAME)}


def _index_names(inspector) -> set[str]:
    return {index["name"] for index in inspector.get_indexes(TABLE_NAME) if index.get("name")}


def _foreign_key_names(inspector) -> set[str]:
    return {
        foreign_key["name"]
        for foreign_key in inspector.get_foreign_keys(TABLE_NAME)
        if foreign_key.get("name")
    }


def upgrade():
    bind = op.get_bind()
    inspector = sa.inspect(bind)

    columns = _column_names(inspector)

    with op.batch_alter_table(TABLE_NAME) as batch:
        if "business_unit_id" not in columns:
            batch.add_column(sa.Column("business_unit_id", sa.Integer(), nullable=True))
        if "client_branch_id" not in columns:
            batch.add_column(sa.Column("client_branch_id", sa.Integer(), nullable=True))

    inspector = sa.inspect(bind)
    foreign_keys = _foreign_key_names(inspector)
    indexes = _index_names(inspector)

    with op.batch_alter_table(TABLE_NAME) as batch:
        if "fk_client_related_persons_business_unit" not in foreign_keys:
            batch.create_foreign_key(
                "fk_client_related_persons_business_unit",
                "client_business_units",
                ["business_unit_id"],
                ["id"],
                ondelete="SET NULL",
            )
        if "fk_client_related_persons_client_branch" not in foreign_keys:
            batch.create_foreign_key(
                "fk_client_related_persons_client_branch",
                "client_branches",
                ["client_branch_id"],
                ["id"],
                ondelete="SET NULL",
            )
        if "ix_client_related_persons_business_unit_id" not in indexes:
            batch.create_index(
                "ix_client_related_persons_business_unit_id",
                ["business_unit_id"],
            )
        if "ix_client_related_persons_client_branch_id" not in indexes:
            batch.create_index(
                "ix_client_related_persons_client_branch_id",
                ["client_branch_id"],
            )


def downgrade():
    bind = op.get_bind()
    inspector = sa.inspect(bind)

    columns = _column_names(inspector)
    indexes = _index_names(inspector)
    foreign_keys = _foreign_key_names(inspector)

    with op.batch_alter_table(TABLE_NAME) as batch:
        if "ix_client_related_persons_client_branch_id" in indexes:
            batch.drop_index("ix_client_related_persons_client_branch_id")
        if "ix_client_related_persons_business_unit_id" in indexes:
            batch.drop_index("ix_client_related_persons_business_unit_id")
        if "fk_client_related_persons_client_branch" in foreign_keys:
            batch.drop_constraint(
                "fk_client_related_persons_client_branch",
                type_="foreignkey",
            )
        if "fk_client_related_persons_business_unit" in foreign_keys:
            batch.drop_constraint(
                "fk_client_related_persons_business_unit",
                type_="foreignkey",
            )
        if "client_branch_id" in columns:
            batch.drop_column("client_branch_id")
        if "business_unit_id" in columns:
            batch.drop_column("business_unit_id")
