"""update identities unique constraint and properties

Revision ID: 549eff097c71
Revises: a3047a624130
Create Date: 2025-02-20 09:53:42.743105

"""

from typing import Sequence, Union

import sqlalchemy as sa
from sqlalchemy.dialects import postgresql

from alembic import op
from letta.settings import settings

# revision identifiers, used by Alembic.
revision: str = "549eff097c71"
down_revision: Union[str, None] = "a3047a624130"
branch_labels: Union[str, Sequence[str], None] = None
depends_on: Union[str, Sequence[str], None] = None


def upgrade() -> None:
    # Skip this migration for SQLite
    if not settings.letta_pg_uri_no_default:
        return

    # ### commands auto generated by Alembic - please adjust! ###
    # Update unique constraint on identities table
    op.drop_constraint("unique_identifier_pid_org_id", "identities", type_="unique")
    op.create_unique_constraint(
        "unique_identifier_without_project",
        "identities",
        ["identifier_key", "project_id", "organization_id"],
        postgresql_nulls_not_distinct=True,
    )

    # Add properties column to identities table
    op.add_column("identities", sa.Column("properties", postgresql.JSONB, nullable=False, server_default="[]"))

    # Create identities_agents table for many-to-many relationship
    op.create_table(
        "identities_agents",
        sa.Column("identity_id", sa.String(), nullable=False),
        sa.Column("agent_id", sa.String(), nullable=False),
        sa.ForeignKeyConstraint(["agent_id"], ["agents.id"], ondelete="CASCADE"),
        sa.ForeignKeyConstraint(["identity_id"], ["identities.id"], ondelete="CASCADE"),
        sa.PrimaryKeyConstraint("identity_id", "agent_id"),
    )

    # Migrate existing relationships
    # First, get existing relationships where identity_id is not null
    op.execute(
        """
        INSERT INTO identities_agents (identity_id, agent_id)
        SELECT DISTINCT identity_id, id as agent_id
        FROM agents
        WHERE identity_id IS NOT NULL
        """
    )

    # Remove old identity_id column from agents
    op.drop_column("agents", "identity_id")
    op.drop_column("agents", "identifier_key")
    # ### end Alembic commands ###


def downgrade() -> None:
    # Skip this migration for SQLite
    if not settings.letta_pg_uri_no_default:
        return

    # ### commands auto generated by Alembic - please adjust! ###
    # Add back the old columns to agents
    op.add_column("agents", sa.Column("identity_id", sa.String(), nullable=True))
    op.add_column("agents", sa.Column("identifier_key", sa.String(), nullable=True))

    # Migrate relationships back
    op.execute(
        """
        UPDATE agents a
        SET identity_id = ia.identity_id
        FROM identities_agents ia
        WHERE a.id = ia.agent_id
        """
    )

    # Drop the many-to-many table
    op.drop_table("identities_agents")

    # Drop properties column
    op.drop_column("identities", "properties")

    # Restore old unique constraint
    op.drop_constraint("unique_identifier_without_project", "identities", type_="unique")
    op.create_unique_constraint("unique_identifier_pid_org_id", "identities", ["identifier_key", "project_id", "organization_id"])
    # ### end Alembic commands ###
