"""phase_2_client_acceptance_controls

Revision ID: 20260622_phase_2_client_acceptance_controls
Revises: 20260621_phase_1_udin_final_documents
Create Date: 2026-06-22
"""
from __future__ import annotations

from alembic import op
import sqlalchemy as sa
from sqlalchemy import inspect, text

revision = "20260622_phase_2_client_acceptance_controls"
down_revision = "20260621_phase_1_udin_final_documents"
branch_labels = None
depends_on = None


CLIENT_TABLE = "clients"


def _columns(table_name: str) -> set[str]:
    bind = op.get_bind()
    inspector = inspect(bind)
    if table_name not in inspector.get_table_names():
        return set()
    return {col["name"] for col in inspector.get_columns(table_name)}


def _add_column_if_missing(existing: set[str], column: sa.Column) -> None:
    if column.name in existing:
        return
    op.add_column(CLIENT_TABLE, column)
    existing.add(column.name)


def _create_index_if_missing(index_name: str, columns: list[str]) -> None:
    bind = op.get_bind()
    inspector = inspect(bind)
    existing_indexes = {idx["name"] for idx in inspector.get_indexes(CLIENT_TABLE)}
    if index_name not in existing_indexes:
        op.create_index(index_name, CLIENT_TABLE, columns)


def upgrade() -> None:
    existing = _columns(CLIENT_TABLE)

    _add_column_if_missing(existing, sa.Column("acceptance_status", sa.String(length=30), nullable=False, server_default="pending_review"))
    _add_column_if_missing(existing, sa.Column("acceptance_required", sa.Boolean(), nullable=False, server_default=sa.true()))
    _add_column_if_missing(existing, sa.Column("independence_check_completed", sa.Boolean(), nullable=False, server_default=sa.false()))
    _add_column_if_missing(existing, sa.Column("conflict_check_completed", sa.Boolean(), nullable=False, server_default=sa.false()))
    _add_column_if_missing(existing, sa.Column("kyc_completed", sa.Boolean(), nullable=False, server_default=sa.false()))
    _add_column_if_missing(existing, sa.Column("engagement_letter_required", sa.Boolean(), nullable=False, server_default=sa.true()))
    _add_column_if_missing(existing, sa.Column("engagement_letter_received", sa.Boolean(), nullable=False, server_default=sa.false()))
    _add_column_if_missing(existing, sa.Column("acceptance_approved_by_user_id", sa.Integer(), nullable=True))
    _add_column_if_missing(existing, sa.Column("acceptance_approved_at_utc", sa.DateTime(timezone=True), nullable=True))
    _add_column_if_missing(existing, sa.Column("acceptance_review_notes", sa.Text(), nullable=True))
    _add_column_if_missing(existing, sa.Column("acceptance_rejection_reason", sa.Text(), nullable=True))

    bind = op.get_bind()
    dialect = bind.dialect.name
    if dialect == "postgresql":
        op.execute(text("UPDATE clients SET acceptance_status = 'pending_review' WHERE acceptance_status IS NULL"))
        op.execute(text("UPDATE clients SET acceptance_required = TRUE WHERE acceptance_required IS NULL"))
        op.execute(text("UPDATE clients SET independence_check_completed = FALSE WHERE independence_check_completed IS NULL"))
        op.execute(text("UPDATE clients SET conflict_check_completed = FALSE WHERE conflict_check_completed IS NULL"))
        op.execute(text("UPDATE clients SET kyc_completed = FALSE WHERE kyc_completed IS NULL"))
        op.execute(text("UPDATE clients SET engagement_letter_required = TRUE WHERE engagement_letter_required IS NULL"))
        op.execute(text("UPDATE clients SET engagement_letter_received = FALSE WHERE engagement_letter_received IS NULL"))
    else:
        op.execute(text("UPDATE clients SET acceptance_status = 'pending_review' WHERE acceptance_status IS NULL"))
        op.execute(text("UPDATE clients SET acceptance_required = 1 WHERE acceptance_required IS NULL"))
        op.execute(text("UPDATE clients SET independence_check_completed = 0 WHERE independence_check_completed IS NULL"))
        op.execute(text("UPDATE clients SET conflict_check_completed = 0 WHERE conflict_check_completed IS NULL"))
        op.execute(text("UPDATE clients SET kyc_completed = 0 WHERE kyc_completed IS NULL"))
        op.execute(text("UPDATE clients SET engagement_letter_required = 1 WHERE engagement_letter_required IS NULL"))
        op.execute(text("UPDATE clients SET engagement_letter_received = 0 WHERE engagement_letter_received IS NULL"))

    _create_index_if_missing("ix_clients_acceptance_status", ["acceptance_status"])
    _create_index_if_missing("ix_clients_acceptance_approved_by_user_id", ["acceptance_approved_by_user_id"])


def downgrade() -> None:
    bind = op.get_bind()
    inspector = inspect(bind)
    if CLIENT_TABLE not in inspector.get_table_names():
        return

    existing_indexes = {idx["name"] for idx in inspector.get_indexes(CLIENT_TABLE)}
    if "ix_clients_acceptance_approved_by_user_id" in existing_indexes:
        op.drop_index("ix_clients_acceptance_approved_by_user_id", table_name=CLIENT_TABLE)
    if "ix_clients_acceptance_status" in existing_indexes:
        op.drop_index("ix_clients_acceptance_status", table_name=CLIENT_TABLE)

    existing = _columns(CLIENT_TABLE)
    for col in [
        "acceptance_rejection_reason",
        "acceptance_review_notes",
        "acceptance_approved_at_utc",
        "acceptance_approved_by_user_id",
        "engagement_letter_received",
        "engagement_letter_required",
        "kyc_completed",
        "conflict_check_completed",
        "independence_check_completed",
        "acceptance_required",
        "acceptance_status",
    ]:
        if col in existing:
            op.drop_column(CLIENT_TABLE, col)
