"""Add changeset_entries and tool_invocations tables.

Provides persistent storage for ChangeSet entries and ToolInvocation
records, replacing the in-memory stores for production use.

Revision ID: d0_001_changeset_artifacts
Revises: c0_002_merge_skill_registry
Create Date: 2026-02-24 00:00:00

"""

from collections.abc import Sequence

import sqlalchemy as sa
from alembic import op

# revision identifiers, used by Alembic.
revision: str = "d0_001_changeset_artifacts"
down_revision: str | Sequence[str] | None = "c0_002_merge_skill_registry"
branch_labels: str | Sequence[str] | None = None
depends_on: str | Sequence[str] | None = None


def upgrade() -> None:
    """Create changeset_entries and tool_invocations tables."""
    op.create_table(
        "changeset_entries",
        sa.Column("entry_id", sa.String(26), primary_key=True),
        sa.Column("changeset_id", sa.String(26), nullable=False),
        sa.Column("plan_id", sa.String(26), nullable=False),
        sa.Column("resource_id", sa.String(26), nullable=False),
        sa.Column("tool_name", sa.String(255), nullable=False),
        sa.Column("operation", sa.String(20), nullable=False),
        sa.Column("path", sa.String(1024), nullable=False),
        sa.Column("before_hash", sa.String(64), nullable=True),
        sa.Column("after_hash", sa.String(64), nullable=True),
        sa.Column("before_mode", sa.Integer, nullable=True),
        sa.Column("after_mode", sa.Integer, nullable=True),
        sa.Column("timestamp", sa.String(30), nullable=False),
    )
    op.create_index(
        "ix_changeset_entries_changeset_id",
        "changeset_entries",
        ["changeset_id"],
    )
    op.create_index(
        "ix_changeset_entries_plan_id",
        "changeset_entries",
        ["plan_id"],
    )
    op.create_index(
        "ix_changeset_entries_path",
        "changeset_entries",
        ["path"],
    )

    op.create_table(
        "tool_invocations",
        sa.Column("invocation_id", sa.String(26), primary_key=True),
        sa.Column("changeset_id", sa.String(26), nullable=True),
        sa.Column("plan_id", sa.String(26), nullable=False),
        sa.Column("tool_name", sa.String(255), nullable=False),
        sa.Column("skill_name", sa.String(255), nullable=True),
        sa.Column("arguments_json", sa.Text, nullable=True),
        sa.Column("result_json", sa.Text, nullable=True),
        sa.Column("error", sa.Text, nullable=True),
        sa.Column("success", sa.Boolean, nullable=False, server_default="1"),
        sa.Column("duration_ms", sa.Float, nullable=False, server_default="0.0"),
        sa.Column("started_at", sa.String(30), nullable=False),
        sa.Column("completed_at", sa.String(30), nullable=True),
        sa.Column("change_ids_json", sa.Text, nullable=True),
        sa.Column("sequence_number", sa.Integer, nullable=False, server_default="0"),
        sa.Column("sandbox_path", sa.String(1024), nullable=True),
        sa.Column("resource_refs_json", sa.Text, nullable=True),
        sa.Column("provider_metadata_json", sa.Text, nullable=True),
    )
    op.create_index(
        "ix_tool_invocations_changeset_id",
        "tool_invocations",
        ["changeset_id"],
    )
    op.create_index(
        "ix_tool_invocations_plan_id",
        "tool_invocations",
        ["plan_id"],
    )
    op.create_index(
        "ix_tool_invocations_tool_name",
        "tool_invocations",
        ["tool_name"],
    )


def downgrade() -> None:
    """Drop changeset_entries and tool_invocations tables."""
    op.drop_table("tool_invocations")
    op.drop_table("changeset_entries")
