"""add Fabric graph read model

Revision ID: y2t3u4v5w6x7
Revises: x1s2t3u4v5w6
Create Date: 2026-05-23

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

revision = "y2t3u4v5w6x7"
down_revision = "x1s2t3u4v5w6"
branch_labels = None
depends_on = None


def upgrade() -> None:
    op.create_table(
        "fabric_graph_imports",
        sa.Column("id", UUID(as_uuid=True), primary_key=True, nullable=False),
        sa.Column("source_repo_slug", sa.String(length=100), nullable=False),
        sa.Column("source_url", sa.Text(), nullable=True),
        sa.Column("source_commit", sa.String(length=80), nullable=True),
        sa.Column("source_path", sa.Text(), nullable=True),
        sa.Column("api_version", sa.String(length=100), nullable=True),
        sa.Column("export_kind", sa.String(length=100), nullable=True),
        sa.Column("exported_at", sa.DateTime(timezone=True), nullable=True),
        sa.Column("content_hash", sa.String(length=64), nullable=False),
        sa.Column("node_count", sa.Integer(), nullable=False, server_default="0"),
        sa.Column("edge_count", sa.Integer(), nullable=False, server_default="0"),
        sa.Column("validation_status", sa.String(length=20), nullable=False, server_default="valid"),
        sa.Column("error_details", JSONB(), nullable=True),
        sa.Column("graph_json", JSONB(), nullable=False, server_default="{}"),
        sa.Column("is_latest", sa.Boolean(), nullable=False, server_default="false"),
        sa.Column("last_seen_at", sa.DateTime(timezone=True), nullable=True),
        sa.Column("created_at", sa.DateTime(timezone=True), nullable=False, server_default=sa.func.now()),
        sa.Column("updated_at", sa.DateTime(timezone=True), nullable=False, server_default=sa.func.now()),
        sa.UniqueConstraint("source_repo_slug", "content_hash", name="uq_fabric_graph_imports_source_hash"),
    )
    op.create_index("ix_fabric_graph_imports_source_repo_slug", "fabric_graph_imports", ["source_repo_slug"])
    op.create_index("ix_fabric_graph_imports_source_commit", "fabric_graph_imports", ["source_commit"])
    op.create_index("ix_fabric_graph_imports_export_kind", "fabric_graph_imports", ["export_kind"])
    op.create_index("ix_fabric_graph_imports_exported_at", "fabric_graph_imports", ["exported_at"])
    op.create_index("ix_fabric_graph_imports_content_hash", "fabric_graph_imports", ["content_hash"])
    op.create_index("ix_fabric_graph_imports_validation_status", "fabric_graph_imports", ["validation_status"])
    op.create_index("ix_fabric_graph_imports_is_latest", "fabric_graph_imports", ["is_latest"])

    op.create_table(
        "fabric_graph_nodes",
        sa.Column("id", UUID(as_uuid=True), primary_key=True, nullable=False),
        sa.Column("import_id", UUID(as_uuid=True), nullable=False),
        sa.Column("source_repo_slug", sa.String(length=100), nullable=False),
        sa.Column("graph_id", sa.Text(), nullable=False),
        sa.Column("kind", sa.String(length=100), nullable=False),
        sa.Column("name", sa.Text(), nullable=False),
        sa.Column("repo_slug", sa.String(length=100), nullable=False),
        sa.Column("domain_slug", sa.String(length=100), nullable=False),
        sa.Column("lifecycle", sa.String(length=50), nullable=False),
        sa.Column("canonical_type", sa.String(length=100), nullable=True),
        sa.Column("canon_category", sa.String(length=100), nullable=True),
        sa.Column("canon_anchor", sa.Text(), nullable=True),
        sa.Column("mapping_fit", sa.String(length=20), nullable=True),
        sa.Column("evidence_state", sa.String(length=20), nullable=True),
        sa.Column("display_only", sa.Boolean(), nullable=False, server_default="false"),
        sa.Column("attributes", JSONB(), nullable=False, server_default="{}"),
        sa.Column("raw_json", JSONB(), nullable=False, server_default="{}"),
        sa.ForeignKeyConstraint(["import_id"], ["fabric_graph_imports.id"], ondelete="CASCADE"),
        sa.UniqueConstraint("import_id", "graph_id", name="uq_fabric_graph_nodes_import_graph_id"),
    )
    op.create_index("ix_fabric_graph_nodes_import_id", "fabric_graph_nodes", ["import_id"])
    op.create_index("ix_fabric_graph_nodes_source_repo_slug", "fabric_graph_nodes", ["source_repo_slug"])
    op.create_index("ix_fabric_graph_nodes_kind", "fabric_graph_nodes", ["kind"])
    op.create_index("ix_fabric_graph_nodes_repo_slug", "fabric_graph_nodes", ["repo_slug"])
    op.create_index("ix_fabric_graph_nodes_domain_slug", "fabric_graph_nodes", ["domain_slug"])
    op.create_index("ix_fabric_graph_nodes_lifecycle", "fabric_graph_nodes", ["lifecycle"])
    op.create_index("ix_fabric_graph_nodes_canonical_type", "fabric_graph_nodes", ["canonical_type"])
    op.create_index("ix_fabric_graph_nodes_canon_category", "fabric_graph_nodes", ["canon_category"])
    op.create_index("ix_fabric_graph_nodes_mapping_fit", "fabric_graph_nodes", ["mapping_fit"])
    op.create_index("ix_fabric_graph_nodes_evidence_state", "fabric_graph_nodes", ["evidence_state"])
    op.create_index("ix_fabric_graph_nodes_display_only", "fabric_graph_nodes", ["display_only"])

    op.create_table(
        "fabric_graph_edges",
        sa.Column("id", UUID(as_uuid=True), primary_key=True, nullable=False),
        sa.Column("import_id", UUID(as_uuid=True), nullable=False),
        sa.Column("source_repo_slug", sa.String(length=100), nullable=False),
        sa.Column("edge_key", sa.String(length=64), nullable=False),
        sa.Column("from_graph_id", sa.Text(), nullable=False),
        sa.Column("to_graph_id", sa.Text(), nullable=False),
        sa.Column("edge_type", sa.String(length=100), nullable=False),
        sa.Column("canonical_type", sa.String(length=100), nullable=True),
        sa.Column("canon_anchor", sa.Text(), nullable=True),
        sa.Column("mapping_fit", sa.String(length=20), nullable=True),
        sa.Column("evidence_state", sa.String(length=20), nullable=True),
        sa.Column("display_only", sa.Boolean(), nullable=False, server_default="false"),
        sa.Column("attributes", JSONB(), nullable=False, server_default="{}"),
        sa.Column("raw_json", JSONB(), nullable=False, server_default="{}"),
        sa.ForeignKeyConstraint(["import_id"], ["fabric_graph_imports.id"], ondelete="CASCADE"),
        sa.UniqueConstraint("import_id", "edge_key", name="uq_fabric_graph_edges_import_edge_key"),
    )
    op.create_index("ix_fabric_graph_edges_import_id", "fabric_graph_edges", ["import_id"])
    op.create_index("ix_fabric_graph_edges_source_repo_slug", "fabric_graph_edges", ["source_repo_slug"])
    op.create_index("ix_fabric_graph_edges_edge_key", "fabric_graph_edges", ["edge_key"])
    op.create_index("ix_fabric_graph_edges_edge_type", "fabric_graph_edges", ["edge_type"])
    op.create_index("ix_fabric_graph_edges_canonical_type", "fabric_graph_edges", ["canonical_type"])
    op.create_index("ix_fabric_graph_edges_mapping_fit", "fabric_graph_edges", ["mapping_fit"])
    op.create_index("ix_fabric_graph_edges_evidence_state", "fabric_graph_edges", ["evidence_state"])
    op.create_index("ix_fabric_graph_edges_display_only", "fabric_graph_edges", ["display_only"])


def downgrade() -> None:
    op.drop_index("ix_fabric_graph_edges_display_only", table_name="fabric_graph_edges")
    op.drop_index("ix_fabric_graph_edges_evidence_state", table_name="fabric_graph_edges")
    op.drop_index("ix_fabric_graph_edges_mapping_fit", table_name="fabric_graph_edges")
    op.drop_index("ix_fabric_graph_edges_canonical_type", table_name="fabric_graph_edges")
    op.drop_index("ix_fabric_graph_edges_edge_type", table_name="fabric_graph_edges")
    op.drop_index("ix_fabric_graph_edges_edge_key", table_name="fabric_graph_edges")
    op.drop_index("ix_fabric_graph_edges_source_repo_slug", table_name="fabric_graph_edges")
    op.drop_index("ix_fabric_graph_edges_import_id", table_name="fabric_graph_edges")
    op.drop_table("fabric_graph_edges")

    op.drop_index("ix_fabric_graph_nodes_display_only", table_name="fabric_graph_nodes")
    op.drop_index("ix_fabric_graph_nodes_evidence_state", table_name="fabric_graph_nodes")
    op.drop_index("ix_fabric_graph_nodes_mapping_fit", table_name="fabric_graph_nodes")
    op.drop_index("ix_fabric_graph_nodes_canon_category", table_name="fabric_graph_nodes")
    op.drop_index("ix_fabric_graph_nodes_canonical_type", table_name="fabric_graph_nodes")
    op.drop_index("ix_fabric_graph_nodes_lifecycle", table_name="fabric_graph_nodes")
    op.drop_index("ix_fabric_graph_nodes_domain_slug", table_name="fabric_graph_nodes")
    op.drop_index("ix_fabric_graph_nodes_repo_slug", table_name="fabric_graph_nodes")
    op.drop_index("ix_fabric_graph_nodes_kind", table_name="fabric_graph_nodes")
    op.drop_index("ix_fabric_graph_nodes_source_repo_slug", table_name="fabric_graph_nodes")
    op.drop_index("ix_fabric_graph_nodes_import_id", table_name="fabric_graph_nodes")
    op.drop_table("fabric_graph_nodes")

    op.drop_index("ix_fabric_graph_imports_is_latest", table_name="fabric_graph_imports")
    op.drop_index("ix_fabric_graph_imports_validation_status", table_name="fabric_graph_imports")
    op.drop_index("ix_fabric_graph_imports_content_hash", table_name="fabric_graph_imports")
    op.drop_index("ix_fabric_graph_imports_exported_at", table_name="fabric_graph_imports")
    op.drop_index("ix_fabric_graph_imports_export_kind", table_name="fabric_graph_imports")
    op.drop_index("ix_fabric_graph_imports_source_commit", table_name="fabric_graph_imports")
    op.drop_index("ix_fabric_graph_imports_source_repo_slug", table_name="fabric_graph_imports")
    op.drop_table("fabric_graph_imports")
