"""add account_id to PSA and notification tables

Revision ID: 8aac5b372402
Revises: a1d2a84b9abb
Create Date: 2026-04-09 00:00:00.000000
"""
from typing import Sequence, Union
from alembic import op
import sqlalchemy as sa

revision: str = '8aac5b372402'
down_revision: Union[str, None] = 'a1d2a84b9abb'
branch_labels: Union[str, Sequence[str], None] = None
depends_on: Union[str, Sequence[str], None] = None


def upgrade() -> None:
    # Step 1: ADD COLUMN
    for table in ('psa_post_log', 'psa_member_mappings', 'notification_logs'):
        op.add_column(table, sa.Column('account_id', sa.UUID(), nullable=True))
        op.create_foreign_key(
            f'fk_{table}_account_id', table, 'accounts',
            ['account_id'], ['id'], ondelete='CASCADE',
        )

    # Step 2: BACKFILL
    # psa_post_log: prefer psa_connection → fallback to posted_by user
    # Note: cannot reference the updated table (ppl) inside the FROM clause JOIN,
    # so use a correlated subquery for psa_connections lookup instead.
    op.execute("""
        UPDATE psa_post_log ppl
        SET account_id = COALESCE(
            (SELECT account_id FROM psa_connections WHERE id = ppl.psa_connection_id),
            u.account_id
        )
        FROM users u
        WHERE ppl.posted_by = u.id
          AND ppl.account_id IS NULL
    """)

    # psa_member_mappings: via psa_connection
    op.execute("""
        UPDATE psa_member_mappings pmm
        SET account_id = pc.account_id
        FROM psa_connections pc
        WHERE pmm.psa_connection_id = pc.id
          AND pmm.account_id IS NULL
    """)

    # notification_logs: via notification_config
    op.execute("""
        UPDATE notification_logs nl
        SET account_id = nc.account_id
        FROM notification_configs nc
        WHERE nl.notification_config_id = nc.id
          AND nl.account_id IS NULL
    """)

    # Step 3: VERIFY
    for table in ('psa_post_log', 'psa_member_mappings', 'notification_logs'):
        result = op.get_bind().execute(
            sa.text(f"SELECT COUNT(*) FROM {table} WHERE account_id IS NULL")
        )
        count = result.scalar()
        if count > 0:
            raise RuntimeError(f"ROLLBACK: {count} NULL account_id rows in {table}.")

    # Step 4: SET NOT NULL
    for table in ('psa_post_log', 'psa_member_mappings', 'notification_logs'):
        op.alter_column(table, 'account_id', nullable=False)

    # Step 5: CREATE INDEX
    for table in ('psa_post_log', 'psa_member_mappings', 'notification_logs'):
        op.create_index(f'ix_{table}_account_id', table, ['account_id'])


def downgrade() -> None:
    for table in ('psa_post_log', 'psa_member_mappings', 'notification_logs'):
        op.drop_index(f'ix_{table}_account_id', table_name=table)
        op.drop_constraint(f'fk_{table}_account_id', table, type_='foreignkey')
        op.drop_column(table, 'account_id')
