"""initial_schema

Revision ID: 20251105
Revises:
Create Date: 2025-11-05 15:05:38.488506

"""

from typing import Sequence, Union

from alembic import op
import sqlalchemy as sa
from sqlalchemy.dialects import postgresql

# Import custom types
from preloop.models.db.vector_types import VectorType

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


def upgrade() -> None:
    """Upgrade schema."""
    # Create pgvector extension first
    op.execute("CREATE EXTENSION IF NOT EXISTS vector")

    # ### commands auto generated by Alembic - please adjust! ###
    # Create account table without foreign key to user (circular dependency)
    op.create_table(
        "account",
        sa.Column(
            "organization_name",
            sa.String(length=255),
            nullable=True,
            comment="Display name for the organization",
        ),
        sa.Column(
            "primary_user_id",
            sa.UUID(),
            nullable=True,
            comment="The account owner/creator",
        ),
        sa.Column("email_verified", sa.Boolean(), nullable=False),
        sa.Column("is_active", sa.Boolean(), nullable=False),
        sa.Column("is_superuser", sa.Boolean(), nullable=False),
        sa.Column(
            "created", sa.DateTime(), server_default=sa.text("now()"), nullable=False
        ),
        sa.Column(
            "last_updated",
            sa.DateTime(),
            server_default=sa.text("now()"),
            nullable=False,
        ),
        sa.Column("meta_data", sa.JSON(), nullable=True),
        sa.Column("stripe_customer_id", sa.String(length=255), nullable=True),
        sa.Column("id", sa.UUID(), nullable=False),
        sa.Column(
            "created_at", sa.DateTime(), server_default=sa.text("now()"), nullable=False
        ),
        sa.Column(
            "updated_at", sa.DateTime(), server_default=sa.text("now()"), nullable=False
        ),
        sa.PrimaryKeyConstraint("id"),
        sa.UniqueConstraint("stripe_customer_id"),
    )
    op.create_index(op.f("ix_account_id"), "account", ["id"], unique=False)
    op.create_table(
        "embeddingmodel",
        sa.Column("name", sa.String(length=255), nullable=False),
        sa.Column("provider", sa.String(length=100), nullable=False),
        sa.Column("version", sa.String(length=100), nullable=False),
        sa.Column("dimensions", sa.Integer(), nullable=False),
        sa.Column("is_active", sa.Boolean(), nullable=False),
        sa.Column("meta_data", sa.JSON(), nullable=True),
        sa.Column("id", sa.UUID(), nullable=False),
        sa.Column(
            "created_at", sa.DateTime(), server_default=sa.text("now()"), nullable=False
        ),
        sa.Column(
            "updated_at", sa.DateTime(), server_default=sa.text("now()"), nullable=False
        ),
        sa.PrimaryKeyConstraint("id"),
        sa.UniqueConstraint("name"),
        sa.UniqueConstraint("provider", "version", name="uix_provider_version"),
    )
    op.create_index(
        op.f("ix_embeddingmodel_id"), "embeddingmodel", ["id"], unique=False
    )
    op.create_table(
        "permission",
        sa.Column(
            "id",
            sa.UUID(),
            nullable=False,
            comment="Unique identifier for the permission",
        ),
        sa.Column(
            "name",
            sa.String(length=100),
            nullable=False,
            comment="Unique permission name",
        ),
        sa.Column(
            "description",
            sa.Text(),
            nullable=False,
            comment="Description of what this permission allows",
        ),
        sa.Column(
            "category",
            sa.String(length=50),
            nullable=False,
            comment="Category for grouping permissions",
        ),
        sa.Column(
            "is_active",
            sa.Boolean(),
            nullable=False,
            comment="Whether permission is active",
        ),
        sa.Column(
            "created_at",
            sa.DateTime(timezone=True),
            server_default=sa.text("now()"),
            nullable=False,
            comment="When the permission was created",
        ),
        sa.Column(
            "updated_at", sa.DateTime(), server_default=sa.text("now()"), nullable=False
        ),
        sa.PrimaryKeyConstraint("id"),
    )
    op.create_index(
        op.f("ix_permission_category"), "permission", ["category"], unique=False
    )
    op.create_index(op.f("ix_permission_name"), "permission", ["name"], unique=True)
    op.create_table(
        "user",
        sa.Column(
            "id", sa.UUID(), nullable=False, comment="Unique identifier for the user"
        ),
        sa.Column(
            "account_id",
            sa.UUID(),
            nullable=False,
            comment="The account this user belongs to",
        ),
        sa.Column(
            "username", sa.String(length=255), nullable=False, comment="Unique username"
        ),
        sa.Column(
            "email",
            sa.String(length=255),
            nullable=False,
            comment="User's email address",
        ),
        sa.Column(
            "email_verified",
            sa.Boolean(),
            nullable=False,
            comment="Whether the email has been verified",
        ),
        sa.Column(
            "full_name",
            sa.String(length=255),
            nullable=True,
            comment="User's full name",
        ),
        sa.Column(
            "hashed_password",
            sa.String(length=255),
            nullable=True,
            comment="Hashed password (null for external auth)",
        ),
        sa.Column(
            "is_active",
            sa.Boolean(),
            nullable=False,
            comment="Whether the user account is active",
        ),
        sa.Column(
            "user_source",
            sa.String(length=50),
            nullable=False,
            comment="Source of authentication: 'local', 'ldap', 'ad', 'saml', 'oauth'",
        ),
        sa.Column(
            "oauth_provider",
            sa.String(length=50),
            nullable=True,
            comment="OAuth provider if user_source is 'oauth'",
        ),
        sa.Column(
            "oauth_id",
            sa.String(length=255),
            nullable=True,
            comment="OAuth provider's user ID",
        ),
        sa.Column(
            "external_id",
            sa.String(length=255),
            nullable=True,
            comment="External system's user ID (for LDAP/AD/SAML)",
        ),
        sa.Column(
            "last_login",
            sa.DateTime(timezone=True),
            nullable=True,
            comment="When the user last logged in",
        ),
        sa.Column(
            "created_at",
            sa.DateTime(timezone=True),
            server_default=sa.text("now()"),
            nullable=False,
            comment="When the user was created",
        ),
        sa.Column(
            "updated_at",
            sa.DateTime(timezone=True),
            server_default=sa.text("now()"),
            nullable=False,
            comment="When the user was last updated",
        ),
        sa.ForeignKeyConstraint(
            ["account_id"], ["account.id"], name="fk_user_account", ondelete="CASCADE"
        ),
        sa.PrimaryKeyConstraint("id"),
    )
    op.create_index(op.f("ix_user_account_id"), "user", ["account_id"], unique=False)
    op.create_index(op.f("ix_user_email"), "user", ["email"], unique=False)
    op.create_index(op.f("ix_user_external_id"), "user", ["external_id"], unique=False)
    op.create_index(op.f("ix_user_user_source"), "user", ["user_source"], unique=False)
    op.create_index(op.f("ix_user_username"), "user", ["username"], unique=True)
    op.create_table(
        "ai_model",
        sa.Column("id", sa.UUID(), nullable=False),
        sa.Column("name", sa.String(length=255), nullable=False),
        sa.Column("description", sa.Text(), nullable=True),
        sa.Column("provider_name", sa.String(length=255), nullable=False),
        sa.Column("model_identifier", sa.String(length=255), nullable=False),
        sa.Column("api_endpoint", sa.String(), nullable=True),
        sa.Column("api_key", sa.String(), nullable=True),
        sa.Column("account_id", sa.UUID(), nullable=True),
        sa.Column("is_default", sa.Boolean(), nullable=False),
        sa.Column(
            "model_parameters", postgresql.JSONB(astext_type=sa.Text()), nullable=True
        ),
        sa.Column("meta_data", postgresql.JSONB(astext_type=sa.Text()), nullable=True),
        sa.Column(
            "created_at", sa.DateTime(), server_default=sa.text("now()"), nullable=False
        ),
        sa.Column(
            "updated_at", sa.DateTime(), server_default=sa.text("now()"), nullable=False
        ),
        sa.ForeignKeyConstraint(
            ["account_id"],
            ["account.id"],
        ),
        sa.PrimaryKeyConstraint("id"),
    )
    op.create_index(
        op.f("ix_ai_model_account_id"), "ai_model", ["account_id"], unique=False
    )
    op.create_index(
        op.f("ix_ai_model_model_identifier"),
        "ai_model",
        ["model_identifier"],
        unique=False,
    )
    op.create_index(op.f("ix_ai_model_name"), "ai_model", ["name"], unique=False)
    op.create_table(
        "api_key",
        sa.Column("id", sa.UUID(), nullable=False),
        sa.Column("name", sa.String(length=100), nullable=False),
        sa.Column("key", sa.String(length=100), nullable=False),
        sa.Column(
            "created_at", sa.DateTime(), server_default=sa.text("now()"), nullable=False
        ),
        sa.Column("expires_at", sa.DateTime(), nullable=True),
        sa.Column("last_used_at", sa.DateTime(), nullable=True),
        sa.Column(
            "user_id",
            sa.UUID(),
            nullable=False,
            comment="The user who created this API key",
        ),
        sa.Column("scopes", sa.JSON(), nullable=False),
        sa.Column("is_active", sa.Boolean(), nullable=False),
        sa.Column(
            "updated_at", sa.DateTime(), server_default=sa.text("now()"), nullable=False
        ),
        sa.ForeignKeyConstraint(["user_id"], ["user.id"], ondelete="CASCADE"),
        sa.PrimaryKeyConstraint("id"),
    )
    op.create_index(op.f("ix_api_key_key"), "api_key", ["key"], unique=True)
    op.create_table(
        "api_usage",
        sa.Column("id", sa.UUID(), nullable=False),
        sa.Column("user_id", sa.UUID(), nullable=True),
        sa.Column("endpoint", sa.String(length=255), nullable=False),
        sa.Column("method", sa.String(length=10), nullable=False),
        sa.Column("status_code", sa.Integer(), nullable=False),
        sa.Column("duration", sa.Float(), nullable=False),
        sa.Column("action_type", sa.String(length=50), nullable=True),
        sa.Column(
            "timestamp", sa.DateTime(), server_default=sa.text("now()"), nullable=False
        ),
        sa.Column(
            "created_at", sa.DateTime(), server_default=sa.text("now()"), nullable=False
        ),
        sa.Column(
            "updated_at", sa.DateTime(), server_default=sa.text("now()"), nullable=False
        ),
        sa.ForeignKeyConstraint(["user_id"], ["user.id"], ondelete="SET NULL"),
        sa.PrimaryKeyConstraint("id"),
    )
    op.create_index(
        op.f("ix_api_usage_timestamp"), "api_usage", ["timestamp"], unique=False
    )
    op.create_index(
        op.f("ix_api_usage_user_id"), "api_usage", ["user_id"], unique=False
    )
    op.create_table(
        "approval_policy",
        sa.Column("id", sa.UUID(), nullable=False),
        sa.Column(
            "account_id",
            sa.UUID(),
            nullable=False,
            comment="The account this policy belongs to",
        ),
        sa.Column(
            "name",
            sa.String(length=255),
            nullable=False,
            comment="Human-readable name for the policy",
        ),
        sa.Column(
            "description",
            sa.String(),
            nullable=True,
            comment="Optional description of what this policy does",
        ),
        sa.Column(
            "approval_type",
            sa.String(length=50),
            nullable=False,
            comment="Type of approval: 'slack', 'mattermost', 'webhook', 'manual'",
        ),
        sa.Column(
            "channel",
            sa.String(length=255),
            nullable=True,
            comment="Channel for approval requests",
        ),
        sa.Column(
            "user",
            sa.String(length=255),
            nullable=True,
            comment="Specific user to request approval from",
        ),
        sa.Column(
            "approval_config",
            sa.JSON(),
            nullable=True,
            comment="Generic configuration for approval mechanism",
        ),
        sa.Column(
            "timeout_seconds",
            sa.Integer(),
            nullable=True,
            comment="How long to wait for approval (default: 5 minutes)",
        ),
        sa.Column(
            "require_reason",
            sa.Boolean(),
            nullable=False,
            comment="Whether approver must provide a reason",
        ),
        sa.Column(
            "is_default",
            sa.Boolean(),
            nullable=False,
            comment="Whether this is the default policy for the account",
        ),
        sa.Column(
            "workflow_type",
            sa.String(length=50),
            nullable=False,
            comment="Type of approval workflow: 'simple', 'multi_stage', 'consensus'",
        ),
        sa.Column(
            "workflow_config",
            sa.JSON(),
            nullable=True,
            comment="Configuration for the approval workflow (stages, teams, voting rules)",
        ),
        sa.Column(
            "approver_user_ids",
            postgresql.ARRAY(sa.UUID()),
            nullable=True,
            comment="List of user IDs who can approve (proprietary)",
        ),
        sa.Column(
            "approver_team_ids",
            postgresql.ARRAY(sa.UUID()),
            nullable=True,
            comment="List of team IDs whose members can approve (proprietary)",
        ),
        sa.Column(
            "approvals_required",
            sa.Integer(),
            nullable=False,
            server_default="1",
            comment="Number of approvals required (quorum) - proprietary",
        ),
        sa.Column(
            "escalation_user_ids",
            postgresql.ARRAY(sa.UUID()),
            nullable=True,
            comment="List of user IDs to escalate to on timeout (proprietary)",
        ),
        sa.Column(
            "escalation_team_ids",
            postgresql.ARRAY(sa.UUID()),
            nullable=True,
            comment="List of team IDs to escalate to on timeout (proprietary)",
        ),
        sa.Column(
            "notification_channels",
            postgresql.ARRAY(sa.String()),
            nullable=False,
            server_default=sa.text("ARRAY['email']::varchar[]"),
            comment="Notification channels: email, mobile_push, slack, mattermost, webhook",
        ),
        sa.Column(
            "channel_configs",
            sa.JSON(),
            nullable=True,
            comment="Configuration for notification channels (Slack/Mattermost/webhook settings)",
        ),
        sa.Column(
            "created_at", sa.DateTime(), server_default=sa.text("now()"), nullable=False
        ),
        sa.Column(
            "updated_at", sa.DateTime(), server_default=sa.text("now()"), nullable=False
        ),
        sa.ForeignKeyConstraint(["account_id"], ["account.id"], ondelete="CASCADE"),
        sa.PrimaryKeyConstraint("id"),
        sa.UniqueConstraint("account_id", "name", name="uq_account_policy_name"),
    )
    op.create_index(
        op.f("ix_approval_policy_account_id"),
        "approval_policy",
        ["account_id"],
        unique=False,
    )
    op.create_index(
        op.f("ix_approval_policy_is_default"),
        "approval_policy",
        ["is_default"],
        unique=False,
    )
    op.create_index(
        op.f("ix_approval_policy_name"), "approval_policy", ["name"], unique=False
    )
    op.create_table(
        "audit_log",
        sa.Column("account_id", sa.UUID(), nullable=False),
        sa.Column("user_id", sa.UUID(), nullable=True),
        sa.Column("action", sa.String(length=100), nullable=False),
        sa.Column("resource_type", sa.String(length=50), nullable=True),
        sa.Column("resource_id", sa.String(length=255), nullable=True),
        sa.Column("status", sa.String(length=20), nullable=False),
        sa.Column("ip_address", sa.String(length=45), nullable=True),
        sa.Column("user_agent", sa.Text(), nullable=True),
        sa.Column("details", postgresql.JSONB(astext_type=sa.Text()), nullable=True),
        sa.Column(
            "timestamp", sa.DateTime(), server_default=sa.text("now()"), nullable=False
        ),
        sa.Column("id", sa.UUID(), nullable=False),
        sa.Column(
            "created_at", sa.DateTime(), server_default=sa.text("now()"), nullable=False
        ),
        sa.Column(
            "updated_at", sa.DateTime(), server_default=sa.text("now()"), nullable=False
        ),
        sa.ForeignKeyConstraint(["account_id"], ["account.id"], ondelete="CASCADE"),
        sa.ForeignKeyConstraint(["user_id"], ["user.id"], ondelete="SET NULL"),
        sa.PrimaryKeyConstraint("id"),
    )
    op.create_index(
        op.f("ix_audit_log_account_id"), "audit_log", ["account_id"], unique=False
    )
    op.create_index(op.f("ix_audit_log_action"), "audit_log", ["action"], unique=False)
    op.create_index(op.f("ix_audit_log_id"), "audit_log", ["id"], unique=False)
    op.create_index(
        op.f("ix_audit_log_resource_id"), "audit_log", ["resource_id"], unique=False
    )
    op.create_index(
        op.f("ix_audit_log_resource_type"), "audit_log", ["resource_type"], unique=False
    )
    op.create_index(op.f("ix_audit_log_status"), "audit_log", ["status"], unique=False)
    op.create_index(
        op.f("ix_audit_log_timestamp"), "audit_log", ["timestamp"], unique=False
    )
    op.create_index(
        op.f("ix_audit_log_user_id"), "audit_log", ["user_id"], unique=False
    )
    op.create_table(
        "client_version_logs",
        sa.Column("id", sa.Integer(), nullable=False),
        sa.Column("ip_address", sa.String(), nullable=False),
        sa.Column("client_version", sa.String(), nullable=False),
        sa.Column(
            "timestamp",
            sa.DateTime(timezone=True),
            server_default=sa.text("now()"),
            nullable=False,
        ),
        sa.Column("account_id", sa.UUID(), nullable=True),
        sa.Column("organization_identifier", sa.String(), nullable=True),
        sa.Column("project_identifier", sa.String(), nullable=True),
        sa.Column(
            "created_at", sa.DateTime(), server_default=sa.text("now()"), nullable=False
        ),
        sa.Column(
            "updated_at", sa.DateTime(), server_default=sa.text("now()"), nullable=False
        ),
        sa.ForeignKeyConstraint(
            ["account_id"],
            ["account.id"],
        ),
        sa.PrimaryKeyConstraint("id"),
    )
    op.create_index(
        op.f("ix_client_version_logs_account_id"),
        "client_version_logs",
        ["account_id"],
        unique=False,
    )
    op.create_index(
        op.f("ix_client_version_logs_id"), "client_version_logs", ["id"], unique=False
    )
    op.create_index(
        op.f("ix_client_version_logs_ip_address"),
        "client_version_logs",
        ["ip_address"],
        unique=False,
    )
    op.create_index(
        op.f("ix_client_version_logs_organization_identifier"),
        "client_version_logs",
        ["organization_identifier"],
        unique=False,
    )
    op.create_index(
        op.f("ix_client_version_logs_project_identifier"),
        "client_version_logs",
        ["project_identifier"],
        unique=False,
    )
    op.create_table(
        "mcp_server",
        sa.Column("id", sa.UUID(), nullable=False),
        sa.Column("account_id", sa.UUID(), nullable=False),
        sa.Column("name", sa.String(length=255), nullable=False),
        sa.Column("url", sa.String(length=1024), nullable=False),
        sa.Column("transport", sa.String(length=50), nullable=False),
        sa.Column("auth_type", sa.String(length=50), nullable=False),
        sa.Column(
            "auth_config", postgresql.JSONB(astext_type=sa.Text()), nullable=True
        ),
        sa.Column("status", sa.String(length=50), nullable=False),
        sa.Column("last_scan_at", sa.String(), nullable=True),
        sa.Column("last_error", sa.Text(), nullable=True),
        sa.Column(
            "created_at", sa.DateTime(), server_default=sa.text("now()"), nullable=False
        ),
        sa.Column(
            "updated_at", sa.DateTime(), server_default=sa.text("now()"), nullable=False
        ),
        sa.ForeignKeyConstraint(
            ["account_id"],
            ["account.id"],
        ),
        sa.PrimaryKeyConstraint("id"),
    )
    op.create_index(
        op.f("ix_mcp_server_account_id"), "mcp_server", ["account_id"], unique=False
    )
    op.create_table(
        "plan",
        sa.Column("id", sa.String(), nullable=False),
        sa.Column("name", sa.String(), nullable=False),
        sa.Column("price_monthly", sa.Float(), nullable=True),
        sa.Column("price_annually", sa.Float(), nullable=True),
        sa.Column("is_active", sa.Boolean(), nullable=False),
        sa.Column("features", postgresql.JSONB(astext_type=sa.Text()), nullable=False),
        sa.Column("stripe_product_id", sa.String(), nullable=True),
        sa.Column("account_id", sa.UUID(), nullable=True),
        sa.Column("is_custom", sa.Boolean(), nullable=False),
        sa.Column(
            "created_at", sa.DateTime(), server_default=sa.text("now()"), nullable=False
        ),
        sa.Column(
            "updated_at", sa.DateTime(), server_default=sa.text("now()"), nullable=False
        ),
        sa.ForeignKeyConstraint(
            ["account_id"],
            ["account.id"],
        ),
        sa.PrimaryKeyConstraint("id"),
        sa.UniqueConstraint("name"),
        sa.UniqueConstraint("stripe_product_id"),
    )
    op.create_index(op.f("ix_plan_account_id"), "plan", ["account_id"], unique=False)
    op.create_table(
        "role",
        sa.Column(
            "id", sa.UUID(), nullable=False, comment="Unique identifier for the role"
        ),
        sa.Column(
            "account_id",
            sa.UUID(),
            nullable=True,
            comment="Account this role belongs to (null for system roles)",
        ),
        sa.Column("name", sa.String(length=100), nullable=False, comment="Role name"),
        sa.Column(
            "description",
            sa.Text(),
            nullable=True,
            comment="Description of what this role allows",
        ),
        sa.Column(
            "is_system_role",
            sa.Boolean(),
            nullable=False,
            comment="Whether this is a system-defined role",
        ),
        sa.Column(
            "created_at",
            sa.DateTime(timezone=True),
            server_default=sa.text("now()"),
            nullable=False,
            comment="When the role was created",
        ),
        sa.Column(
            "updated_at",
            sa.DateTime(timezone=True),
            server_default=sa.text("now()"),
            nullable=False,
            comment="When the role was last updated",
        ),
        sa.ForeignKeyConstraint(["account_id"], ["account.id"], ondelete="CASCADE"),
        sa.PrimaryKeyConstraint("id"),
        sa.UniqueConstraint("account_id", "name", name="uq_account_role_name"),
    )
    op.create_index(op.f("ix_role_account_id"), "role", ["account_id"], unique=False)
    op.create_index(
        op.f("ix_role_is_system_role"), "role", ["is_system_role"], unique=False
    )
    op.create_index(op.f("ix_role_name"), "role", ["name"], unique=False)
    op.create_table(
        "team",
        sa.Column(
            "id", sa.UUID(), nullable=False, comment="Unique identifier for the team"
        ),
        sa.Column(
            "account_id",
            sa.UUID(),
            nullable=False,
            comment="The account this team belongs to",
        ),
        sa.Column(
            "name",
            sa.String(length=255),
            nullable=False,
            comment="Human-readable name for the team",
        ),
        sa.Column(
            "description",
            sa.Text(),
            nullable=True,
            comment="Optional description of the team's purpose",
        ),
        sa.Column(
            "created_at",
            sa.DateTime(timezone=True),
            server_default=sa.text("now()"),
            nullable=False,
            comment="When the team was created",
        ),
        sa.Column(
            "updated_at",
            sa.DateTime(timezone=True),
            server_default=sa.text("now()"),
            nullable=False,
            comment="When the team was last modified",
        ),
        sa.ForeignKeyConstraint(["account_id"], ["account.id"], ondelete="CASCADE"),
        sa.PrimaryKeyConstraint("id"),
        sa.UniqueConstraint("account_id", "name", name="uq_account_team_name"),
    )
    op.create_index(op.f("ix_team_account_id"), "team", ["account_id"], unique=False)
    op.create_index(op.f("ix_team_name"), "team", ["name"], unique=False)
    op.create_table(
        "tracker",
        sa.Column("name", sa.String(length=255), nullable=False),
        sa.Column(
            "tracker_type",
            sa.String(length=50),
            nullable=False,
            comment="Possible values: github, gitlab, jira",
        ),
        sa.Column(
            "url",
            sa.String(length=1000),
            nullable=True,
            comment="URL to the tracker (required for Jira, optional for others)",
        ),
        sa.Column(
            "api_key",
            sa.String(length=1000),
            nullable=False,
            comment="Encrypted API key or token for authentication",
        ),
        sa.Column("is_active", sa.Boolean(), nullable=False),
        sa.Column(
            "is_deleted", sa.Boolean(), nullable=False, comment="Flag for soft deletion"
        ),
        sa.Column(
            "is_owner_managed",
            sa.Boolean(),
            nullable=False,
            comment="If True, the account that owns this tracker also owns all organizations linked to it",
        ),
        sa.Column("connection_details", sa.JSON(), nullable=True),
        sa.Column("meta_data", sa.JSON(), nullable=True),
        sa.Column(
            "subscribed_events",
            sa.JSON(),
            nullable=True,
            comment="List of specific webhook event names to subscribe to (e.g., ['push', 'issues']). Empty or None might imply default/all events based on client logic.",
        ),
        sa.Column(
            "jira_webhook_id",
            sa.String(length=255),
            nullable=True,
            comment="Stored Jira Webhook ID",
        ),
        sa.Column(
            "jira_webhook_secret",
            sa.String(length=255),
            nullable=True,
            comment="Secret used to validate incoming Jira webhooks. Store encrypted if possible.",
        ),
        sa.Column("account_id", sa.UUID(), nullable=False),
        sa.Column("is_valid", sa.Boolean(), nullable=False),
        sa.Column("last_validation", sa.DateTime(), nullable=True),
        sa.Column("validation_message", sa.String(length=1000), nullable=True),
        sa.Column(
            "created", sa.DateTime(), server_default=sa.text("now()"), nullable=False
        ),
        sa.Column(
            "last_updated",
            sa.DateTime(),
            server_default=sa.text("now()"),
            nullable=False,
        ),
        sa.Column("id", sa.UUID(), nullable=False),
        sa.Column(
            "created_at", sa.DateTime(), server_default=sa.text("now()"), nullable=False
        ),
        sa.Column(
            "updated_at", sa.DateTime(), server_default=sa.text("now()"), nullable=False
        ),
        sa.ForeignKeyConstraint(["account_id"], ["account.id"], ondelete="CASCADE"),
        sa.PrimaryKeyConstraint("id"),
    )
    op.create_index(
        op.f("ix_tracker_account_id"), "tracker", ["account_id"], unique=False
    )
    op.create_index(op.f("ix_tracker_id"), "tracker", ["id"], unique=False)
    op.create_index(
        op.f("ix_tracker_is_deleted"), "tracker", ["is_deleted"], unique=False
    )
    op.create_table(
        "user_invitation",
        sa.Column(
            "id",
            sa.UUID(),
            nullable=False,
            comment="Unique identifier for the invitation",
        ),
        sa.Column(
            "account_id",
            sa.UUID(),
            nullable=False,
            comment="The account the user is being invited to",
        ),
        sa.Column(
            "email",
            sa.String(length=255),
            nullable=False,
            comment="Email address of the invitee",
        ),
        sa.Column(
            "invited_by",
            sa.UUID(),
            nullable=False,
            comment="User who sent the invitation",
        ),
        sa.Column(
            "token",
            sa.String(length=64),
            nullable=False,
            comment="Secure token for the invitation link",
        ),
        sa.Column(
            "status",
            sa.String(length=20),
            nullable=False,
            comment="Current status of the invitation",
        ),
        sa.Column(
            "role_ids",
            sa.String(length=500),
            nullable=True,
            comment="Comma-separated role UUIDs to assign on acceptance",
        ),
        sa.Column(
            "created_at",
            sa.DateTime(timezone=True),
            server_default=sa.text("now()"),
            nullable=False,
            comment="When the invitation was created",
        ),
        sa.Column(
            "expires_at",
            sa.DateTime(timezone=True),
            nullable=False,
            comment="When the invitation expires",
        ),
        sa.Column(
            "accepted_at",
            sa.DateTime(timezone=True),
            nullable=True,
            comment="When the invitation was accepted",
        ),
        sa.Column(
            "accepted_by",
            sa.UUID(),
            nullable=True,
            comment="User created when invitation was accepted",
        ),
        sa.Column(
            "updated_at", sa.DateTime(), server_default=sa.text("now()"), nullable=False
        ),
        sa.ForeignKeyConstraint(["accepted_by"], ["user.id"], ondelete="SET NULL"),
        sa.ForeignKeyConstraint(["account_id"], ["account.id"], ondelete="CASCADE"),
        sa.ForeignKeyConstraint(["invited_by"], ["user.id"], ondelete="CASCADE"),
        sa.PrimaryKeyConstraint("id"),
    )
    op.create_index(
        op.f("ix_user_invitation_account_id"),
        "user_invitation",
        ["account_id"],
        unique=False,
    )
    op.create_index(
        op.f("ix_user_invitation_email"), "user_invitation", ["email"], unique=False
    )
    op.create_index(
        op.f("ix_user_invitation_status"), "user_invitation", ["status"], unique=False
    )
    op.create_index(
        op.f("ix_user_invitation_token"), "user_invitation", ["token"], unique=True
    )
    op.create_table(
        "notification_preferences",
        sa.Column(
            "id",
            sa.UUID(),
            nullable=False,
            comment="Unique identifier for the notification preferences",
        ),
        sa.Column(
            "user_id",
            sa.UUID(),
            nullable=False,
            comment="Reference to the user",
        ),
        sa.Column(
            "preferred_channel",
            sa.String(length=50),
            nullable=False,
            server_default="email",
            comment="Preferred notification channel: 'email' or 'mobile_push'",
        ),
        sa.Column(
            "mobile_device_tokens",
            postgresql.JSONB(astext_type=sa.Text()),
            nullable=True,
            comment="List of mobile device tokens: [{platform: 'ios'|'android', token: '...', registered_at: '...'}]",
        ),
        sa.Column(
            "enable_email",
            sa.Boolean(),
            nullable=False,
            server_default=sa.text("true"),
            comment="Whether email notifications are enabled",
        ),
        sa.Column(
            "enable_mobile_push",
            sa.Boolean(),
            nullable=False,
            server_default=sa.text("false"),
            comment="Whether mobile push notifications are enabled",
        ),
        sa.Column(
            "created_at",
            sa.DateTime(timezone=True),
            server_default=sa.text("now()"),
            nullable=False,
            comment="When the preferences were created",
        ),
        sa.Column(
            "updated_at",
            sa.DateTime(timezone=True),
            server_default=sa.text("now()"),
            nullable=False,
            comment="When the preferences were last updated",
        ),
        sa.ForeignKeyConstraint(["user_id"], ["user.id"], ondelete="CASCADE"),
        sa.PrimaryKeyConstraint("id"),
    )
    op.create_index(
        op.f("ix_notification_preferences_user_id"),
        "notification_preferences",
        ["user_id"],
        unique=True,
    )
    op.create_table(
        "flow",
        sa.Column("name", sa.String(), nullable=False),
        sa.Column("description", sa.Text(), nullable=True),
        sa.Column("icon", sa.String(), nullable=True),
        sa.Column("trigger_event_source", sa.String(), nullable=True),
        sa.Column("trigger_event_type", sa.String(), nullable=True),
        sa.Column("trigger_organization_id", sa.String(), nullable=True),
        sa.Column("trigger_project_id", sa.String(), nullable=True),
        sa.Column("trigger_config", sa.JSON(), nullable=True),
        sa.Column("webhook_config", sa.JSON(), nullable=True),
        sa.Column("prompt_template", sa.Text(), nullable=False),
        sa.Column("ai_model_id", sa.UUID(), nullable=True),
        sa.Column("agent_type", sa.String(), nullable=False),
        sa.Column("agent_config", sa.JSON(), nullable=False),
        sa.Column("allowed_mcp_servers", sa.JSON(), nullable=False),
        sa.Column("allowed_mcp_tools", sa.JSON(), nullable=False),
        sa.Column("git_clone_config", sa.JSON(), nullable=True),
        sa.Column("custom_commands", sa.JSON(), nullable=True),
        sa.Column("is_preset", sa.Boolean(), nullable=False),
        sa.Column("is_enabled", sa.Boolean(), nullable=False),
        sa.Column("account_id", sa.UUID(), nullable=True),
        sa.Column("id", sa.UUID(), nullable=False),
        sa.Column(
            "created_at", sa.DateTime(), server_default=sa.text("now()"), nullable=False
        ),
        sa.Column(
            "updated_at", sa.DateTime(), server_default=sa.text("now()"), nullable=False
        ),
        sa.ForeignKeyConstraint(
            ["account_id"],
            ["account.id"],
        ),
        sa.ForeignKeyConstraint(
            ["ai_model_id"],
            ["ai_model.id"],
        ),
        sa.PrimaryKeyConstraint("id"),
    )
    op.create_index(op.f("ix_flow_account_id"), "flow", ["account_id"], unique=False)
    op.create_index(op.f("ix_flow_id"), "flow", ["id"], unique=False)
    op.create_table(
        "issue_set",
        sa.Column("name", sa.String(length=255), nullable=False),
        sa.Column(
            "issue_ids",
            postgresql.JSONB(astext_type=sa.Text()),
            server_default=sa.text("'[]'::jsonb"),
            nullable=False,
        ),
        sa.Column("ai_model_id", sa.UUID(), nullable=True),
        sa.Column("meta_data", postgresql.JSONB(astext_type=sa.Text()), nullable=True),
        sa.Column("id", sa.UUID(), nullable=False),
        sa.Column(
            "created_at", sa.DateTime(), server_default=sa.text("now()"), nullable=False
        ),
        sa.Column(
            "updated_at", sa.DateTime(), server_default=sa.text("now()"), nullable=False
        ),
        sa.ForeignKeyConstraint(
            ["ai_model_id"],
            ["ai_model.id"],
        ),
        sa.PrimaryKeyConstraint("id"),
    )
    op.create_index(
        op.f("ix_issue_set_ai_model_id"), "issue_set", ["ai_model_id"], unique=False
    )
    op.create_index(op.f("ix_issue_set_id"), "issue_set", ["id"], unique=False)
    op.create_index(op.f("ix_issue_set_name"), "issue_set", ["name"], unique=False)
    op.create_table(
        "mcp_tool",
        sa.Column("id", sa.UUID(), nullable=False),
        sa.Column("mcp_server_id", sa.UUID(), nullable=False),
        sa.Column("name", sa.String(length=255), nullable=False),
        sa.Column("description", sa.Text(), nullable=True),
        sa.Column(
            "input_schema", postgresql.JSONB(astext_type=sa.Text()), nullable=False
        ),
        sa.Column("discovered_at", sa.String(), nullable=False),
        sa.Column(
            "created_at", sa.DateTime(), server_default=sa.text("now()"), nullable=False
        ),
        sa.Column(
            "updated_at", sa.DateTime(), server_default=sa.text("now()"), nullable=False
        ),
        sa.ForeignKeyConstraint(
            ["mcp_server_id"],
            ["mcp_server.id"],
        ),
        sa.PrimaryKeyConstraint("id"),
    )
    op.create_index(
        op.f("ix_mcp_tool_mcp_server_id"), "mcp_tool", ["mcp_server_id"], unique=False
    )
    op.create_index(op.f("ix_mcp_tool_name"), "mcp_tool", ["name"], unique=False)
    op.create_table(
        "organization",
        sa.Column("name", sa.String(length=255), nullable=False),
        sa.Column("identifier", sa.String(length=100), nullable=False),
        sa.Column("description", sa.String(length=1000), nullable=True),
        sa.Column("is_active", sa.Boolean(), nullable=False),
        sa.Column("settings", sa.JSON(), nullable=True),
        sa.Column("meta_data", sa.JSON(), nullable=True),
        sa.Column("webhook_secret", sa.String(length=255), nullable=True),
        sa.Column("last_webhook_update", sa.DateTime(timezone=True), nullable=True),
        sa.Column("last_polling_update", sa.DateTime(timezone=True), nullable=True),
        sa.Column("tracker_id", sa.UUID(), nullable=False),
        sa.Column("id", sa.UUID(), nullable=False),
        sa.Column(
            "created_at", sa.DateTime(), server_default=sa.text("now()"), nullable=False
        ),
        sa.Column(
            "updated_at", sa.DateTime(), server_default=sa.text("now()"), nullable=False
        ),
        sa.ForeignKeyConstraint(["tracker_id"], ["tracker.id"], ondelete="CASCADE"),
        sa.PrimaryKeyConstraint("id"),
    )
    op.create_index(op.f("ix_organization_id"), "organization", ["id"], unique=False)
    op.create_index(
        op.f("ix_organization_identifier"), "organization", ["identifier"], unique=False
    )
    op.create_index(
        op.f("ix_organization_tracker_id"), "organization", ["tracker_id"], unique=False
    )
    op.create_table(
        "role_permission",
        sa.Column("id", sa.UUID(), nullable=False, comment="Unique identifier"),
        sa.Column(
            "role_id", sa.UUID(), nullable=False, comment="Reference to the role"
        ),
        sa.Column(
            "permission_id",
            sa.UUID(),
            nullable=False,
            comment="Reference to the permission",
        ),
        sa.Column(
            "granted_at",
            sa.DateTime(timezone=True),
            server_default=sa.text("now()"),
            nullable=False,
            comment="When this permission was granted",
        ),
        sa.Column(
            "created_at", sa.DateTime(), server_default=sa.text("now()"), nullable=False
        ),
        sa.Column(
            "updated_at", sa.DateTime(), server_default=sa.text("now()"), nullable=False
        ),
        sa.ForeignKeyConstraint(
            ["permission_id"], ["permission.id"], ondelete="CASCADE"
        ),
        sa.ForeignKeyConstraint(["role_id"], ["role.id"], ondelete="CASCADE"),
        sa.PrimaryKeyConstraint("id"),
        sa.UniqueConstraint("role_id", "permission_id", name="uq_role_permission"),
    )
    op.create_index(
        op.f("ix_role_permission_permission_id"),
        "role_permission",
        ["permission_id"],
        unique=False,
    )
    op.create_index(
        op.f("ix_role_permission_role_id"), "role_permission", ["role_id"], unique=False
    )
    op.create_table(
        "subscription",
        sa.Column(
            "id", sa.UUID(), server_default=sa.text("gen_random_uuid()"), nullable=False
        ),
        sa.Column("account_id", sa.UUID(), nullable=False),
        sa.Column("plan_id", sa.String(), nullable=False),
        sa.Column("status", sa.String(), nullable=False),
        sa.Column("current_period_start", sa.DateTime(timezone=True), nullable=False),
        sa.Column("current_period_end", sa.DateTime(timezone=True), nullable=False),
        sa.Column("stripe_subscription_id", sa.String(), nullable=True),
        sa.Column(
            "created_at", sa.DateTime(), server_default=sa.text("now()"), nullable=False
        ),
        sa.Column(
            "updated_at", sa.DateTime(), server_default=sa.text("now()"), nullable=False
        ),
        sa.ForeignKeyConstraint(
            ["account_id"],
            ["account.id"],
        ),
        sa.ForeignKeyConstraint(
            ["plan_id"],
            ["plan.id"],
        ),
        sa.PrimaryKeyConstraint("id"),
        sa.UniqueConstraint("stripe_subscription_id"),
    )
    op.create_index(
        op.f("ix_subscription_account_id"), "subscription", ["account_id"], unique=False
    )
    op.create_index(
        op.f("ix_subscription_plan_id"), "subscription", ["plan_id"], unique=False
    )
    op.create_table(
        "team_membership",
        sa.Column(
            "id",
            sa.UUID(),
            nullable=False,
            comment="Unique identifier for the membership",
        ),
        sa.Column(
            "team_id", sa.UUID(), nullable=False, comment="Reference to the team"
        ),
        sa.Column(
            "user_id", sa.UUID(), nullable=False, comment="Reference to the user"
        ),
        sa.Column(
            "role",
            sa.String(length=50),
            nullable=True,
            comment="Optional role within the team (e.g., 'member', 'lead')",
        ),
        sa.Column(
            "added_by", sa.UUID(), nullable=True, comment="User who added this member"
        ),
        sa.Column(
            "added_at",
            sa.DateTime(timezone=True),
            server_default=sa.text("now()"),
            nullable=False,
            comment="When the user was added to the team",
        ),
        sa.Column(
            "created_at", sa.DateTime(), server_default=sa.text("now()"), nullable=False
        ),
        sa.Column(
            "updated_at", sa.DateTime(), server_default=sa.text("now()"), nullable=False
        ),
        sa.ForeignKeyConstraint(["added_by"], ["user.id"], ondelete="SET NULL"),
        sa.ForeignKeyConstraint(["team_id"], ["team.id"], ondelete="CASCADE"),
        sa.ForeignKeyConstraint(["user_id"], ["user.id"], ondelete="CASCADE"),
        sa.PrimaryKeyConstraint("id"),
        sa.UniqueConstraint("team_id", "user_id", name="uq_team_user"),
    )
    op.create_index(
        op.f("ix_team_membership_team_id"), "team_membership", ["team_id"], unique=False
    )
    op.create_index(
        op.f("ix_team_membership_user_id"), "team_membership", ["user_id"], unique=False
    )
    op.create_table(
        "team_role",
        sa.Column("id", sa.UUID(), nullable=False, comment="Unique identifier"),
        sa.Column(
            "team_id", sa.UUID(), nullable=False, comment="Reference to the team"
        ),
        sa.Column(
            "role_id", sa.UUID(), nullable=False, comment="Reference to the role"
        ),
        sa.Column(
            "granted_by", sa.UUID(), nullable=True, comment="User who granted this role"
        ),
        sa.Column(
            "granted_at",
            sa.DateTime(timezone=True),
            server_default=sa.text("now()"),
            nullable=False,
            comment="When the role was granted",
        ),
        sa.Column(
            "created_at", sa.DateTime(), server_default=sa.text("now()"), nullable=False
        ),
        sa.Column(
            "updated_at", sa.DateTime(), server_default=sa.text("now()"), nullable=False
        ),
        sa.ForeignKeyConstraint(["granted_by"], ["user.id"], ondelete="SET NULL"),
        sa.ForeignKeyConstraint(["role_id"], ["role.id"], ondelete="CASCADE"),
        sa.ForeignKeyConstraint(["team_id"], ["team.id"], ondelete="CASCADE"),
        sa.PrimaryKeyConstraint("id"),
        sa.UniqueConstraint("team_id", "role_id", name="uq_team_role"),
    )
    op.create_index(
        op.f("ix_team_role_role_id"), "team_role", ["role_id"], unique=False
    )
    op.create_index(
        op.f("ix_team_role_team_id"), "team_role", ["team_id"], unique=False
    )
    op.create_table(
        "tool_configuration",
        sa.Column("id", sa.UUID(), nullable=False),
        sa.Column(
            "tool_name",
            sa.String(length=255),
            nullable=False,
            comment="Name of the tool",
        ),
        sa.Column(
            "tool_source",
            sa.String(length=50),
            nullable=False,
            comment="Source type: 'builtin', 'mcp', 'http'",
        ),
        sa.Column(
            "mcp_server_id",
            sa.UUID(),
            nullable=True,
            comment="Reference to MCP server (if tool_source='mcp')",
        ),
        sa.Column(
            "http_endpoint_id",
            sa.UUID(),
            nullable=True,
            comment="Reference to HTTP endpoint (future: if tool_source='http')",
        ),
        sa.Column(
            "is_enabled",
            sa.Boolean(),
            nullable=False,
            comment="Whether the tool is enabled",
        ),
        sa.Column(
            "approval_policy_id",
            sa.UUID(),
            nullable=True,
            comment="Reference to approval policy (if set, tool requires approval)",
        ),
        sa.Column(
            "tool_description",
            sa.String(),
            nullable=True,
            comment="Description of what the tool does",
        ),
        sa.Column(
            "tool_schema",
            sa.JSON(),
            nullable=True,
            comment="JSON schema for tool parameters",
        ),
        sa.Column(
            "custom_config",
            sa.JSON(),
            nullable=True,
            comment="Additional configuration options",
        ),
        sa.Column("account_id", sa.UUID(), nullable=False),
        sa.Column(
            "created_at", sa.DateTime(), server_default=sa.text("now()"), nullable=False
        ),
        sa.Column(
            "updated_at", sa.DateTime(), server_default=sa.text("now()"), nullable=False
        ),
        sa.ForeignKeyConstraint(["account_id"], ["account.id"], ondelete="CASCADE"),
        sa.ForeignKeyConstraint(
            ["approval_policy_id"], ["approval_policy.id"], ondelete="SET NULL"
        ),
        sa.ForeignKeyConstraint(
            ["mcp_server_id"], ["mcp_server.id"], ondelete="CASCADE"
        ),
        sa.PrimaryKeyConstraint("id"),
        sa.UniqueConstraint(
            "account_id",
            "tool_name",
            "tool_source",
            "mcp_server_id",
            name="uq_account_tool_source",
        ),
    )
    op.create_index(
        op.f("ix_tool_configuration_account_id"),
        "tool_configuration",
        ["account_id"],
        unique=False,
    )
    op.create_index(
        op.f("ix_tool_configuration_approval_policy_id"),
        "tool_configuration",
        ["approval_policy_id"],
        unique=False,
    )
    op.create_index(
        op.f("ix_tool_configuration_tool_name"),
        "tool_configuration",
        ["tool_name"],
        unique=False,
    )
    op.create_index(
        op.f("ix_tool_configuration_tool_source"),
        "tool_configuration",
        ["tool_source"],
        unique=False,
    )
    op.create_table(
        "tracker_scope_rule",
        sa.Column("tracker_id", sa.UUID(), nullable=False),
        sa.Column(
            "scope_type",
            sa.String(length=50),
            nullable=False,
            comment="Possible values: ORGANIZATION, PROJECT",
        ),
        sa.Column(
            "rule_type",
            sa.String(length=50),
            nullable=False,
            comment="Possible values: INCLUDE, EXCLUDE",
        ),
        sa.Column(
            "identifier",
            sa.String(length=255),
            nullable=False,
            comment="e.g., 'my-org' or 'my-org/my-repo'",
        ),
        sa.Column("id", sa.UUID(), nullable=False),
        sa.Column(
            "created_at", sa.DateTime(), server_default=sa.text("now()"), nullable=False
        ),
        sa.Column(
            "updated_at", sa.DateTime(), server_default=sa.text("now()"), nullable=False
        ),
        sa.ForeignKeyConstraint(["tracker_id"], ["tracker.id"], ondelete="CASCADE"),
        sa.PrimaryKeyConstraint("id"),
    )
    op.create_index(
        op.f("ix_tracker_scope_rule_id"), "tracker_scope_rule", ["id"], unique=False
    )
    op.create_index(
        op.f("ix_tracker_scope_rule_tracker_id"),
        "tracker_scope_rule",
        ["tracker_id"],
        unique=False,
    )
    op.create_table(
        "user_role",
        sa.Column("id", sa.UUID(), nullable=False, comment="Unique identifier"),
        sa.Column(
            "user_id", sa.UUID(), nullable=False, comment="Reference to the user"
        ),
        sa.Column(
            "role_id", sa.UUID(), nullable=False, comment="Reference to the role"
        ),
        sa.Column(
            "granted_by", sa.UUID(), nullable=True, comment="User who granted this role"
        ),
        sa.Column(
            "granted_at",
            sa.DateTime(timezone=True),
            server_default=sa.text("now()"),
            nullable=False,
            comment="When the role was granted",
        ),
        sa.Column(
            "created_at", sa.DateTime(), server_default=sa.text("now()"), nullable=False
        ),
        sa.Column(
            "updated_at", sa.DateTime(), server_default=sa.text("now()"), nullable=False
        ),
        sa.ForeignKeyConstraint(["granted_by"], ["user.id"], ondelete="SET NULL"),
        sa.ForeignKeyConstraint(["role_id"], ["role.id"], ondelete="CASCADE"),
        sa.ForeignKeyConstraint(["user_id"], ["user.id"], ondelete="CASCADE"),
        sa.PrimaryKeyConstraint("id"),
        sa.UniqueConstraint("user_id", "role_id", name="uq_user_role"),
    )
    op.create_index(
        op.f("ix_user_role_role_id"), "user_role", ["role_id"], unique=False
    )
    op.create_index(
        op.f("ix_user_role_user_id"), "user_role", ["user_id"], unique=False
    )
    op.create_table(
        "approval_request",
        sa.Column(
            "id",
            sa.UUID(),
            nullable=False,
            comment="Unique identifier for the approval request",
        ),
        sa.Column(
            "account_id",
            sa.UUID(),
            nullable=False,
            comment="The account this approval request belongs to",
        ),
        sa.Column(
            "tool_configuration_id",
            sa.UUID(),
            nullable=False,
            comment="Reference to the tool configuration",
        ),
        sa.Column(
            "approval_policy_id",
            sa.UUID(),
            nullable=False,
            comment="Reference to the approval policy",
        ),
        sa.Column(
            "execution_id",
            sa.String(length=255),
            nullable=True,
            comment="Flow execution ID (if applicable)",
        ),
        sa.Column(
            "tool_name",
            sa.String(length=255),
            nullable=False,
            comment="Name of the tool being executed",
        ),
        sa.Column(
            "tool_args",
            postgresql.JSONB(astext_type=sa.Text()),
            nullable=False,
            comment="Arguments passed to the tool",
        ),
        sa.Column(
            "agent_reasoning",
            sa.Text(),
            nullable=True,
            comment="Agent's reasoning for the tool call",
        ),
        sa.Column(
            "status",
            sa.Enum(
                "pending",
                "approved",
                "declined",
                "expired",
                "cancelled",
                name="approval_request_status",
            ),
            nullable=False,
            comment="Current status of the approval request",
        ),
        sa.Column(
            "requested_at",
            sa.DateTime(),
            nullable=False,
            comment="When the approval was requested",
        ),
        sa.Column(
            "resolved_at",
            sa.DateTime(),
            nullable=True,
            comment="When the approval was resolved (approved/declined)",
        ),
        sa.Column(
            "expires_at",
            sa.DateTime(),
            nullable=True,
            comment="When the approval request expires",
        ),
        sa.Column(
            "approver_comment",
            sa.Text(),
            nullable=True,
            comment="Comment from the approver",
        ),
        sa.Column(
            "approvals_received",
            sa.Integer(),
            nullable=False,
            server_default="0",
            comment="Number of approvals received so far (for quorum tracking)",
        ),
        sa.Column(
            "approvals_list",
            postgresql.JSONB(astext_type=sa.Text()),
            nullable=True,
            comment="List of approval records: [{user_id, comment, timestamp}]",
        ),
        sa.Column(
            "webhook_posted_at",
            sa.DateTime(),
            nullable=True,
            comment="When the webhook notification was posted",
        ),
        sa.Column(
            "webhook_error",
            sa.Text(),
            nullable=True,
            comment="Error message if webhook posting failed",
        ),
        sa.Column(
            "approval_token",
            sa.String(length=64),
            nullable=False,
            comment="Secure token for public approval links",
        ),
        sa.Column(
            "created_at", sa.DateTime(), server_default=sa.text("now()"), nullable=False
        ),
        sa.Column(
            "updated_at", sa.DateTime(), server_default=sa.text("now()"), nullable=False
        ),
        sa.ForeignKeyConstraint(["account_id"], ["account.id"], ondelete="CASCADE"),
        sa.ForeignKeyConstraint(
            ["approval_policy_id"], ["approval_policy.id"], ondelete="CASCADE"
        ),
        sa.ForeignKeyConstraint(
            ["tool_configuration_id"], ["tool_configuration.id"], ondelete="CASCADE"
        ),
        sa.PrimaryKeyConstraint("id"),
    )
    op.create_index(
        op.f("ix_approval_request_account_id"),
        "approval_request",
        ["account_id"],
        unique=False,
    )
    op.create_index(
        op.f("ix_approval_request_approval_policy_id"),
        "approval_request",
        ["approval_policy_id"],
        unique=False,
    )
    op.create_index(
        op.f("ix_approval_request_approval_token"),
        "approval_request",
        ["approval_token"],
        unique=True,
    )
    op.create_index(
        op.f("ix_approval_request_execution_id"),
        "approval_request",
        ["execution_id"],
        unique=False,
    )
    op.create_index(
        op.f("ix_approval_request_requested_at"),
        "approval_request",
        ["requested_at"],
        unique=False,
    )
    op.create_index(
        op.f("ix_approval_request_status"), "approval_request", ["status"], unique=False
    )
    op.create_index(
        op.f("ix_approval_request_tool_configuration_id"),
        "approval_request",
        ["tool_configuration_id"],
        unique=False,
    )
    op.create_table(
        "tool_approval_conditions",
        sa.Column(
            "id",
            sa.UUID(),
            nullable=False,
            comment="Unique identifier for the approval condition",
        ),
        sa.Column(
            "account_id",
            sa.UUID(),
            nullable=False,
            comment="The account this condition belongs to",
        ),
        sa.Column(
            "tool_configuration_id",
            sa.UUID(),
            nullable=False,
            comment="Reference to the tool configuration (1:1 relationship)",
        ),
        sa.Column(
            "name",
            sa.String(length=255),
            nullable=True,
            comment="Optional human-readable name for the condition",
        ),
        sa.Column(
            "description",
            sa.Text(),
            nullable=True,
            comment="Optional description of what this condition does",
        ),
        sa.Column(
            "is_enabled",
            sa.Boolean(),
            nullable=False,
            comment="Whether the condition is currently active",
        ),
        sa.Column(
            "condition_type",
            sa.String(length=50),
            nullable=False,
            comment="Type of condition evaluator: 'argument', 'state', 'risk'",
        ),
        sa.Column(
            "condition_expression",
            sa.Text(),
            nullable=True,
            comment="CEL expression for conditional approval (proprietary feature)",
        ),
        sa.Column(
            "condition_config",
            sa.JSON(),
            nullable=True,
            comment="Additional configuration for the condition evaluator",
        ),
        sa.Column(
            "created_at",
            sa.DateTime(timezone=True),
            server_default=sa.text("now()"),
            nullable=False,
            comment="When the condition was created",
        ),
        sa.Column(
            "updated_at",
            sa.DateTime(timezone=True),
            server_default=sa.text("now()"),
            nullable=False,
            comment="When the condition was last modified",
        ),
        sa.ForeignKeyConstraint(["account_id"], ["account.id"], ondelete="CASCADE"),
        sa.ForeignKeyConstraint(
            ["tool_configuration_id"], ["tool_configuration.id"], ondelete="CASCADE"
        ),
        sa.PrimaryKeyConstraint("id"),
        sa.UniqueConstraint("tool_configuration_id", name="uq_tool_config_condition"),
    )
    op.create_index(
        op.f("ix_tool_approval_conditions_account_id"),
        "tool_approval_conditions",
        ["account_id"],
        unique=False,
    )
    op.create_index(
        op.f("ix_tool_approval_conditions_condition_type"),
        "tool_approval_conditions",
        ["condition_type"],
        unique=False,
    )
    op.create_index(
        op.f("ix_tool_approval_conditions_is_enabled"),
        "tool_approval_conditions",
        ["is_enabled"],
        unique=False,
    )
    op.create_index(
        op.f("ix_tool_approval_conditions_tool_configuration_id"),
        "tool_approval_conditions",
        ["tool_configuration_id"],
        unique=True,  # 1:1 relationship
    )
    op.create_table(
        "flow_execution",
        sa.Column("id", sa.UUID(), nullable=False),
        sa.Column("flow_id", sa.UUID(), nullable=False),
        sa.Column("trigger_event_id", sa.String(), nullable=True),
        sa.Column(
            "trigger_event_details",
            postgresql.JSONB(astext_type=sa.Text()),
            nullable=True,
        ),
        sa.Column("status", sa.String(), nullable=False),
        sa.Column("start_time", sa.DateTime(), nullable=False),
        sa.Column("end_time", sa.DateTime(), nullable=True),
        sa.Column("resolved_input_prompt", sa.Text(), nullable=True),
        sa.Column("model_output_summary", sa.Text(), nullable=True),
        sa.Column(
            "actions_taken_summary",
            postgresql.JSONB(astext_type=sa.Text()),
            nullable=True,
        ),
        sa.Column(
            "mcp_usage_logs", postgresql.JSONB(astext_type=sa.Text()), nullable=True
        ),
        sa.Column(
            "execution_logs", postgresql.JSONB(astext_type=sa.Text()), nullable=True
        ),
        sa.Column("agent_session_reference", sa.String(), nullable=True),
        sa.Column("error_message", sa.Text(), nullable=True),
        sa.Column("created_at", sa.DateTime(), nullable=False),
        sa.Column("updated_at", sa.DateTime(), nullable=False),
        sa.ForeignKeyConstraint(
            ["flow_id"],
            ["flow.id"],
        ),
        sa.PrimaryKeyConstraint("id"),
    )
    op.create_index(
        op.f("ix_flow_execution_flow_id"), "flow_execution", ["flow_id"], unique=False
    )
    op.create_index(
        op.f("ix_flow_execution_status"), "flow_execution", ["status"], unique=False
    )
    op.create_index(
        op.f("ix_flow_execution_trigger_event_id"),
        "flow_execution",
        ["trigger_event_id"],
        unique=False,
    )
    op.create_table(
        "monthly_usage",
        sa.Column(
            "id", sa.UUID(), server_default=sa.text("gen_random_uuid()"), nullable=False
        ),
        sa.Column("subscription_id", sa.UUID(), nullable=False),
        sa.Column("billing_cycle_start", sa.Date(), nullable=False),
        sa.Column("billing_cycle_end", sa.Date(), nullable=False),
        sa.Column(
            "usage_counts",
            postgresql.JSONB(astext_type=sa.Text()),
            server_default=sa.text("'{}'::jsonb"),
            nullable=False,
        ),
        sa.Column(
            "created_at", sa.DateTime(), server_default=sa.text("now()"), nullable=False
        ),
        sa.Column(
            "updated_at", sa.DateTime(), server_default=sa.text("now()"), nullable=False
        ),
        sa.ForeignKeyConstraint(
            ["subscription_id"],
            ["subscription.id"],
        ),
        sa.PrimaryKeyConstraint("id"),
    )
    op.create_index(
        op.f("ix_monthly_usage_subscription_id"),
        "monthly_usage",
        ["subscription_id"],
        unique=False,
    )
    op.create_table(
        "project",
        sa.Column("name", sa.String(length=255), nullable=False),
        sa.Column("identifier", sa.String(length=100), nullable=False),
        sa.Column("slug", sa.String(length=255), nullable=True),
        sa.Column("description", sa.String(length=1000), nullable=True),
        sa.Column("is_active", sa.Boolean(), nullable=False),
        sa.Column("organization_id", sa.UUID(), nullable=False),
        sa.Column("settings", sa.JSON(), nullable=True),
        sa.Column("tracker_settings", sa.JSON(), nullable=True),
        sa.Column("meta_data", sa.JSON(), nullable=True),
        sa.Column(
            "webhook_last_verified_at", sa.DateTime(timezone=True), nullable=True
        ),
        sa.Column("id", sa.UUID(), nullable=False),
        sa.Column(
            "created_at", sa.DateTime(), server_default=sa.text("now()"), nullable=False
        ),
        sa.Column(
            "updated_at", sa.DateTime(), server_default=sa.text("now()"), nullable=False
        ),
        sa.ForeignKeyConstraint(
            ["organization_id"], ["organization.id"], ondelete="CASCADE"
        ),
        sa.PrimaryKeyConstraint("id"),
    )
    op.create_index(op.f("ix_project_id"), "project", ["id"], unique=False)
    op.create_index(
        op.f("ix_project_identifier"), "project", ["identifier"], unique=False
    )
    op.create_index(
        op.f("ix_project_organization_id"), "project", ["organization_id"], unique=False
    )
    op.create_index(op.f("ix_project_slug"), "project", ["slug"], unique=False)
    op.create_table(
        "issue",
        sa.Column("title", sa.String(length=255), nullable=False),
        sa.Column("description", sa.String(length=5000), nullable=True),
        sa.Column("status", sa.String(length=50), nullable=False),
        sa.Column("priority", sa.String(length=50), nullable=True),
        sa.Column("issue_type", sa.String(length=50), nullable=False),
        sa.Column("external_id", sa.String(length=255), nullable=False),
        sa.Column("external_url", sa.String(length=1000), nullable=True),
        sa.Column("key", sa.String(length=512), nullable=True),
        sa.Column("project_id", sa.UUID(), nullable=False),
        sa.Column("tracker_id", sa.UUID(), nullable=False),
        sa.Column("parent_id", sa.UUID(), nullable=True),
        sa.Column("meta_data", sa.JSON(), nullable=True),
        sa.Column("last_updated_external", sa.DateTime(), nullable=True),
        sa.Column("last_synced", sa.DateTime(), nullable=True),
        sa.Column("id", sa.UUID(), nullable=False),
        sa.Column(
            "created_at", sa.DateTime(), server_default=sa.text("now()"), nullable=False
        ),
        sa.Column(
            "updated_at", sa.DateTime(), server_default=sa.text("now()"), nullable=False
        ),
        sa.ForeignKeyConstraint(["parent_id"], ["issue.id"], ondelete="SET NULL"),
        sa.ForeignKeyConstraint(["project_id"], ["project.id"], ondelete="CASCADE"),
        sa.ForeignKeyConstraint(["tracker_id"], ["tracker.id"], ondelete="CASCADE"),
        sa.PrimaryKeyConstraint("id"),
    )
    op.create_index(op.f("ix_issue_id"), "issue", ["id"], unique=False)
    op.create_index(op.f("ix_issue_key"), "issue", ["key"], unique=False)
    op.create_index(op.f("ix_issue_parent_id"), "issue", ["parent_id"], unique=False)
    op.create_index(op.f("ix_issue_project_id"), "issue", ["project_id"], unique=False)
    op.create_index(op.f("ix_issue_tracker_id"), "issue", ["tracker_id"], unique=False)
    op.create_table(
        "webhook",
        sa.Column("external_id", sa.String(length=255), nullable=False),
        sa.Column("url", sa.String(length=1024), nullable=False),
        sa.Column("secret", sa.String(length=255), nullable=False),
        sa.Column("events", sa.JSON(), nullable=False),
        sa.Column("project_id", sa.UUID(), nullable=True),
        sa.Column("organization_id", sa.UUID(), nullable=True),
        sa.Column("id", sa.UUID(), nullable=False),
        sa.Column(
            "created_at", sa.DateTime(), server_default=sa.text("now()"), nullable=False
        ),
        sa.Column(
            "updated_at", sa.DateTime(), server_default=sa.text("now()"), nullable=False
        ),
        sa.ForeignKeyConstraint(
            ["organization_id"], ["organization.id"], ondelete="CASCADE"
        ),
        sa.ForeignKeyConstraint(["project_id"], ["project.id"], ondelete="CASCADE"),
        sa.PrimaryKeyConstraint("id"),
    )
    op.create_index(
        op.f("ix_webhook_external_id"), "webhook", ["external_id"], unique=False
    )
    op.create_index(op.f("ix_webhook_id"), "webhook", ["id"], unique=False)
    op.create_index(
        op.f("ix_webhook_organization_id"), "webhook", ["organization_id"], unique=False
    )
    op.create_index(
        op.f("ix_webhook_project_id"), "webhook", ["project_id"], unique=False
    )
    op.create_table(
        "comment",
        sa.Column("body", sa.Text(), nullable=False),
        sa.Column(
            "type",
            sa.String(length=50),
            nullable=False,
            comment="Type of comment (e.g., 'issue', 'merge_request')",
        ),
        sa.Column(
            "external_id",
            sa.String(length=36),
            nullable=False,
            comment="External ID of the comment",
        ),
        sa.Column("issue_id", sa.UUID(), nullable=True),
        sa.Column("author", sa.String(length=255), nullable=True),
        sa.Column("tracker_id", sa.UUID(), nullable=False),
        sa.Column("meta_data", sa.JSON(), nullable=True),
        sa.Column("id", sa.UUID(), nullable=False),
        sa.Column(
            "created_at", sa.DateTime(), server_default=sa.text("now()"), nullable=False
        ),
        sa.Column(
            "updated_at", sa.DateTime(), server_default=sa.text("now()"), nullable=False
        ),
        sa.ForeignKeyConstraint(["issue_id"], ["issue.id"], ondelete="CASCADE"),
        sa.ForeignKeyConstraint(["tracker_id"], ["tracker.id"], ondelete="CASCADE"),
        sa.PrimaryKeyConstraint("id"),
    )
    op.create_index(op.f("ix_comment_author"), "comment", ["author"], unique=False)
    op.create_index(op.f("ix_comment_id"), "comment", ["id"], unique=False)
    op.create_index(op.f("ix_comment_issue_id"), "comment", ["issue_id"], unique=False)
    op.create_index(
        op.f("ix_comment_tracker_id"), "comment", ["tracker_id"], unique=False
    )
    op.create_table(
        "issue_duplicate",
        sa.Column("issue1_id", sa.UUID(), nullable=False),
        sa.Column("issue2_id", sa.UUID(), nullable=False),
        sa.Column("decision", sa.String(), nullable=False),
        sa.Column(
            "decision_at", sa.DateTime(), server_default=sa.text("now()"), nullable=True
        ),
        sa.Column("ai_model_id", sa.UUID(), nullable=False),
        sa.Column("ai_model_name", sa.String(), nullable=True),
        sa.Column("reason", sa.Text(), nullable=True),
        sa.Column("suggestion", sa.Text(), nullable=True),
        sa.Column("resolution", sa.String(), nullable=True),
        sa.Column("resolution_at", sa.DateTime(), nullable=True),
        sa.Column("resolution_reason", sa.Text(), nullable=True),
        sa.Column("resulting_issue1_id", sa.UUID(), nullable=True),
        sa.Column("resulting_issue2_id", sa.UUID(), nullable=True),
        sa.Column("id", sa.UUID(), nullable=False),
        sa.Column(
            "created_at", sa.DateTime(), server_default=sa.text("now()"), nullable=False
        ),
        sa.Column(
            "updated_at", sa.DateTime(), server_default=sa.text("now()"), nullable=False
        ),
        sa.ForeignKeyConstraint(
            ["ai_model_id"],
            ["ai_model.id"],
        ),
        sa.ForeignKeyConstraint(
            ["issue1_id"],
            ["issue.id"],
        ),
        sa.ForeignKeyConstraint(
            ["issue2_id"],
            ["issue.id"],
        ),
        sa.ForeignKeyConstraint(
            ["resulting_issue1_id"],
            ["issue.id"],
        ),
        sa.ForeignKeyConstraint(
            ["resulting_issue2_id"],
            ["issue.id"],
        ),
        sa.PrimaryKeyConstraint("id"),
    )
    op.create_index(
        op.f("ix_issue_duplicate_id"), "issue_duplicate", ["id"], unique=False
    )
    op.create_table(
        "issue_relationship",
        sa.Column("source_issue_id", sa.UUID(), nullable=False),
        sa.Column("target_issue_id", sa.UUID(), nullable=False),
        sa.Column("type", sa.String(length=50), nullable=False),
        sa.Column("reason", sa.Text(), nullable=True),
        sa.Column("confidence_score", sa.Float(), nullable=True),
        sa.Column("is_committed", sa.Boolean(), nullable=False),
        sa.Column("comes_from_tracker", sa.Boolean(), nullable=False),
        sa.Column("id", sa.UUID(), nullable=False),
        sa.Column(
            "created_at", sa.DateTime(), server_default=sa.text("now()"), nullable=False
        ),
        sa.Column(
            "updated_at", sa.DateTime(), server_default=sa.text("now()"), nullable=False
        ),
        sa.ForeignKeyConstraint(["source_issue_id"], ["issue.id"], ondelete="CASCADE"),
        sa.ForeignKeyConstraint(["target_issue_id"], ["issue.id"], ondelete="CASCADE"),
        sa.PrimaryKeyConstraint("source_issue_id", "target_issue_id", "type", "id"),
    )
    op.create_index(
        op.f("ix_issue_relationship_id"), "issue_relationship", ["id"], unique=False
    )
    op.create_table(
        "issuecomplianceresult",
        sa.Column("prompt_id", sa.String(), nullable=False),
        sa.Column("name", sa.String(), nullable=False),
        sa.Column("compliance_factor", sa.Float(), nullable=False),
        sa.Column("reason", sa.String(), nullable=False),
        sa.Column("suggestion", sa.String(), nullable=False),
        sa.Column("annotated_description", sa.JSON(), nullable=True),
        sa.Column("issue_id", sa.UUID(), nullable=False),
        sa.Column("id", sa.UUID(), nullable=False),
        sa.Column(
            "created_at", sa.DateTime(), server_default=sa.text("now()"), nullable=False
        ),
        sa.Column(
            "updated_at", sa.DateTime(), server_default=sa.text("now()"), nullable=False
        ),
        sa.ForeignKeyConstraint(["issue_id"], ["issue.id"], ondelete="CASCADE"),
        sa.PrimaryKeyConstraint("id"),
    )
    op.create_index(
        op.f("ix_issuecomplianceresult_id"),
        "issuecomplianceresult",
        ["id"],
        unique=False,
    )
    op.create_index(
        op.f("ix_issuecomplianceresult_issue_id"),
        "issuecomplianceresult",
        ["issue_id"],
        unique=False,
    )
    op.create_table(
        "issueembedding",
        sa.Column("issue_id", sa.UUID(), nullable=False),
        sa.Column("comment_id", sa.UUID(), nullable=True),
        sa.Column("embedding_model_id", sa.UUID(), nullable=False),
        sa.Column(
            "embedding", VectorType(1536), nullable=False, comment="Embedding vector"
        ),
        sa.Column("meta_data", sa.JSON(), nullable=True),
        sa.Column(
            "created_at", sa.DateTime(), server_default=sa.text("now()"), nullable=False
        ),
        sa.Column("id", sa.UUID(), nullable=False),
        sa.Column(
            "updated_at", sa.DateTime(), server_default=sa.text("now()"), nullable=False
        ),
        sa.ForeignKeyConstraint(["comment_id"], ["comment.id"], ondelete="CASCADE"),
        sa.ForeignKeyConstraint(
            ["embedding_model_id"], ["embeddingmodel.id"], ondelete="CASCADE"
        ),
        sa.ForeignKeyConstraint(["issue_id"], ["issue.id"], ondelete="CASCADE"),
        sa.PrimaryKeyConstraint("id"),
        sa.UniqueConstraint(
            "issue_id",
            "comment_id",
            "embedding_model_id",
            name="uix_issue_embedding_model",
        ),
    )
    op.create_index(
        op.f("ix_issueembedding_comment_id"),
        "issueembedding",
        ["comment_id"],
        unique=False,
    )
    op.create_index(
        op.f("ix_issueembedding_embedding_model_id"),
        "issueembedding",
        ["embedding_model_id"],
        unique=False,
    )
    op.create_index(
        op.f("ix_issueembedding_id"), "issueembedding", ["id"], unique=False
    )
    op.create_index(
        op.f("ix_issueembedding_issue_id"), "issueembedding", ["issue_id"], unique=False
    )

    # Add foreign key constraint for account.primary_user_id after both tables exist
    op.create_foreign_key(
        "fk_account_primary_user",
        "account",
        "user",
        ["primary_user_id"],
        ["id"],
        ondelete="SET NULL",
    )
    # ### end Alembic commands ###


def downgrade() -> None:
    """Downgrade schema."""
    # ### commands auto generated by Alembic - please adjust! ###
    op.drop_index(op.f("ix_issueembedding_issue_id"), table_name="issueembedding")
    op.drop_index(op.f("ix_issueembedding_id"), table_name="issueembedding")
    op.drop_index(
        op.f("ix_issueembedding_embedding_model_id"), table_name="issueembedding"
    )
    op.drop_index(op.f("ix_issueembedding_comment_id"), table_name="issueembedding")
    op.drop_table("issueembedding")
    op.drop_index(
        op.f("ix_issuecomplianceresult_issue_id"), table_name="issuecomplianceresult"
    )
    op.drop_index(
        op.f("ix_issuecomplianceresult_id"), table_name="issuecomplianceresult"
    )
    op.drop_table("issuecomplianceresult")
    op.drop_index(op.f("ix_issue_relationship_id"), table_name="issue_relationship")
    op.drop_table("issue_relationship")
    op.drop_index(op.f("ix_issue_duplicate_id"), table_name="issue_duplicate")
    op.drop_table("issue_duplicate")
    op.drop_index(op.f("ix_comment_tracker_id"), table_name="comment")
    op.drop_index(op.f("ix_comment_issue_id"), table_name="comment")
    op.drop_index(op.f("ix_comment_id"), table_name="comment")
    op.drop_index(op.f("ix_comment_author"), table_name="comment")
    op.drop_table("comment")
    op.drop_index(op.f("ix_webhook_project_id"), table_name="webhook")
    op.drop_index(op.f("ix_webhook_organization_id"), table_name="webhook")
    op.drop_index(op.f("ix_webhook_id"), table_name="webhook")
    op.drop_index(op.f("ix_webhook_external_id"), table_name="webhook")
    op.drop_table("webhook")
    op.drop_index(op.f("ix_issue_tracker_id"), table_name="issue")
    op.drop_index(op.f("ix_issue_project_id"), table_name="issue")
    op.drop_index(op.f("ix_issue_parent_id"), table_name="issue")
    op.drop_index(op.f("ix_issue_key"), table_name="issue")
    op.drop_index(op.f("ix_issue_id"), table_name="issue")
    op.drop_table("issue")
    op.drop_index(op.f("ix_project_slug"), table_name="project")
    op.drop_index(op.f("ix_project_organization_id"), table_name="project")
    op.drop_index(op.f("ix_project_identifier"), table_name="project")
    op.drop_index(op.f("ix_project_id"), table_name="project")
    op.drop_table("project")
    op.drop_index(op.f("ix_monthly_usage_subscription_id"), table_name="monthly_usage")
    op.drop_table("monthly_usage")
    op.drop_index(
        op.f("ix_flow_execution_trigger_event_id"), table_name="flow_execution"
    )
    op.drop_index(op.f("ix_flow_execution_status"), table_name="flow_execution")
    op.drop_index(op.f("ix_flow_execution_flow_id"), table_name="flow_execution")
    op.drop_table("flow_execution")
    op.drop_index(
        op.f("ix_tool_approval_conditions_tool_configuration_id"),
        table_name="tool_approval_conditions",
    )
    op.drop_index(
        op.f("ix_tool_approval_conditions_is_enabled"),
        table_name="tool_approval_conditions",
    )
    op.drop_index(
        op.f("ix_tool_approval_conditions_condition_type"),
        table_name="tool_approval_conditions",
    )
    op.drop_index(
        op.f("ix_tool_approval_conditions_account_id"),
        table_name="tool_approval_conditions",
    )
    op.drop_table("tool_approval_conditions")
    op.drop_index(
        op.f("ix_approval_request_tool_configuration_id"), table_name="approval_request"
    )
    op.drop_index(op.f("ix_approval_request_status"), table_name="approval_request")
    op.drop_index(
        op.f("ix_approval_request_requested_at"), table_name="approval_request"
    )
    op.drop_index(
        op.f("ix_approval_request_execution_id"), table_name="approval_request"
    )
    op.drop_index(
        op.f("ix_approval_request_approval_token"), table_name="approval_request"
    )
    op.drop_index(
        op.f("ix_approval_request_approval_policy_id"), table_name="approval_request"
    )
    op.drop_index(op.f("ix_approval_request_account_id"), table_name="approval_request")
    op.drop_table("approval_request")
    op.drop_index(op.f("ix_user_role_user_id"), table_name="user_role")
    op.drop_index(op.f("ix_user_role_role_id"), table_name="user_role")
    op.drop_table("user_role")
    op.drop_index(
        op.f("ix_tracker_scope_rule_tracker_id"), table_name="tracker_scope_rule"
    )
    op.drop_index(op.f("ix_tracker_scope_rule_id"), table_name="tracker_scope_rule")
    op.drop_table("tracker_scope_rule")
    op.drop_index(
        op.f("ix_tool_configuration_tool_source"), table_name="tool_configuration"
    )
    op.drop_index(
        op.f("ix_tool_configuration_tool_name"), table_name="tool_configuration"
    )
    op.drop_index(
        op.f("ix_tool_configuration_approval_policy_id"),
        table_name="tool_configuration",
    )
    op.drop_index(
        op.f("ix_tool_configuration_account_id"), table_name="tool_configuration"
    )
    op.drop_table("tool_configuration")
    op.drop_index(op.f("ix_team_role_team_id"), table_name="team_role")
    op.drop_index(op.f("ix_team_role_role_id"), table_name="team_role")
    op.drop_table("team_role")
    op.drop_index(op.f("ix_team_membership_user_id"), table_name="team_membership")
    op.drop_index(op.f("ix_team_membership_team_id"), table_name="team_membership")
    op.drop_table("team_membership")
    op.drop_index(op.f("ix_subscription_plan_id"), table_name="subscription")
    op.drop_index(op.f("ix_subscription_account_id"), table_name="subscription")
    op.drop_table("subscription")
    op.drop_index(op.f("ix_role_permission_role_id"), table_name="role_permission")
    op.drop_index(
        op.f("ix_role_permission_permission_id"), table_name="role_permission"
    )
    op.drop_table("role_permission")
    op.drop_index(op.f("ix_organization_tracker_id"), table_name="organization")
    op.drop_index(op.f("ix_organization_identifier"), table_name="organization")
    op.drop_index(op.f("ix_organization_id"), table_name="organization")
    op.drop_table("organization")
    op.drop_index(op.f("ix_mcp_tool_name"), table_name="mcp_tool")
    op.drop_index(op.f("ix_mcp_tool_mcp_server_id"), table_name="mcp_tool")
    op.drop_table("mcp_tool")
    op.drop_index(op.f("ix_issue_set_name"), table_name="issue_set")
    op.drop_index(op.f("ix_issue_set_id"), table_name="issue_set")
    op.drop_index(op.f("ix_issue_set_ai_model_id"), table_name="issue_set")
    op.drop_table("issue_set")
    op.drop_index(op.f("ix_flow_id"), table_name="flow")
    op.drop_index(op.f("ix_flow_account_id"), table_name="flow")
    op.drop_table("flow")
    op.drop_index(
        op.f("ix_notification_preferences_user_id"),
        table_name="notification_preferences",
    )
    op.drop_table("notification_preferences")
    op.drop_index(op.f("ix_user_invitation_token"), table_name="user_invitation")
    op.drop_index(op.f("ix_user_invitation_status"), table_name="user_invitation")
    op.drop_index(op.f("ix_user_invitation_email"), table_name="user_invitation")
    op.drop_index(op.f("ix_user_invitation_account_id"), table_name="user_invitation")
    op.drop_table("user_invitation")
    op.drop_index(op.f("ix_tracker_is_deleted"), table_name="tracker")
    op.drop_index(op.f("ix_tracker_id"), table_name="tracker")
    op.drop_index(op.f("ix_tracker_account_id"), table_name="tracker")
    op.drop_table("tracker")
    op.drop_index(op.f("ix_team_name"), table_name="team")
    op.drop_index(op.f("ix_team_account_id"), table_name="team")
    op.drop_table("team")
    op.drop_index(op.f("ix_role_name"), table_name="role")
    op.drop_index(op.f("ix_role_is_system_role"), table_name="role")
    op.drop_index(op.f("ix_role_account_id"), table_name="role")
    op.drop_table("role")
    op.drop_index(op.f("ix_plan_account_id"), table_name="plan")
    op.drop_table("plan")
    op.drop_index(op.f("ix_mcp_server_account_id"), table_name="mcp_server")
    op.drop_table("mcp_server")
    op.drop_index(
        op.f("ix_client_version_logs_project_identifier"),
        table_name="client_version_logs",
    )
    op.drop_index(
        op.f("ix_client_version_logs_organization_identifier"),
        table_name="client_version_logs",
    )
    op.drop_index(
        op.f("ix_client_version_logs_ip_address"), table_name="client_version_logs"
    )
    op.drop_index(op.f("ix_client_version_logs_id"), table_name="client_version_logs")
    op.drop_index(
        op.f("ix_client_version_logs_account_id"), table_name="client_version_logs"
    )
    op.drop_table("client_version_logs")
    op.drop_index(op.f("ix_audit_log_user_id"), table_name="audit_log")
    op.drop_index(op.f("ix_audit_log_timestamp"), table_name="audit_log")
    op.drop_index(op.f("ix_audit_log_status"), table_name="audit_log")
    op.drop_index(op.f("ix_audit_log_resource_type"), table_name="audit_log")
    op.drop_index(op.f("ix_audit_log_resource_id"), table_name="audit_log")
    op.drop_index(op.f("ix_audit_log_id"), table_name="audit_log")
    op.drop_index(op.f("ix_audit_log_action"), table_name="audit_log")
    op.drop_index(op.f("ix_audit_log_account_id"), table_name="audit_log")
    op.drop_table("audit_log")
    op.drop_index(op.f("ix_approval_policy_name"), table_name="approval_policy")
    op.drop_index(op.f("ix_approval_policy_is_default"), table_name="approval_policy")
    op.drop_index(op.f("ix_approval_policy_account_id"), table_name="approval_policy")
    op.drop_table("approval_policy")
    op.drop_index(op.f("ix_api_usage_user_id"), table_name="api_usage")
    op.drop_index(op.f("ix_api_usage_timestamp"), table_name="api_usage")
    op.drop_table("api_usage")
    op.drop_index(op.f("ix_api_key_key"), table_name="api_key")
    op.drop_table("api_key")
    op.drop_index(op.f("ix_ai_model_name"), table_name="ai_model")
    op.drop_index(op.f("ix_ai_model_model_identifier"), table_name="ai_model")
    op.drop_index(op.f("ix_ai_model_account_id"), table_name="ai_model")
    op.drop_table("ai_model")
    op.drop_index(op.f("ix_user_username"), table_name="user")
    op.drop_index(op.f("ix_user_user_source"), table_name="user")
    op.drop_index(op.f("ix_user_external_id"), table_name="user")
    op.drop_index(op.f("ix_user_email"), table_name="user")
    op.drop_index(op.f("ix_user_account_id"), table_name="user")
    op.drop_table("user")
    op.drop_index(op.f("ix_permission_name"), table_name="permission")
    op.drop_index(op.f("ix_permission_category"), table_name="permission")
    op.drop_table("permission")
    op.drop_index(op.f("ix_embeddingmodel_id"), table_name="embeddingmodel")
    op.drop_table("embeddingmodel")

    # Drop foreign key constraint before dropping account table
    op.drop_constraint("fk_account_primary_user", "account", type_="foreignkey")
    op.drop_index(op.f("ix_account_id"), table_name="account")
    op.drop_table("account")
    # ### end Alembic commands ###
