"""Codegen Manifest: manifest_runs table for run-scoped session tokens.

Revision ID: 043
Revises: 042
"""
from alembic import op
import sqlalchemy as sa
from sqlalchemy.dialects import postgresql
from sqlalchemy.dialects.postgresql import ENUM as PgEnum

revision = "043"
down_revision = "042"
branch_labels = None
depends_on = None


def upgrade() -> None:
    op.execute("""
        DO $$ BEGIN
            CREATE TYPE p2hs_manifest_run_status AS ENUM ('active', 'completed', 'failed', 'expired');
        EXCEPTION WHEN duplicate_object THEN NULL;
        END $$
    """)

    op.create_table(
        "manifest_runs",
        sa.Column("id", postgresql.UUID(as_uuid=True), primary_key=True),
        sa.Column(
            "project_id",
            postgresql.UUID(as_uuid=True),
            sa.ForeignKey("projects.id", ondelete="CASCADE"),
            nullable=False,
        ),
        sa.Column(
            "initiated_by",
            postgresql.UUID(as_uuid=True),
            sa.ForeignKey("users.id", ondelete="SET NULL"),
            nullable=True,
        ),
        sa.Column(
            "status",
            PgEnum(name="p2hs_manifest_run_status", create_type=False),
            nullable=False,
            server_default="active",
        ),
        # Scopes the AI agent requested at run start
        sa.Column("requested_scopes", postgresql.JSONB, nullable=True),
        # SHA-256 of the token — the plain token is returned once then discarded
        sa.Column("token_hash", sa.String(64), nullable=False, unique=True),
        sa.Column("expires_at", sa.DateTime(timezone=True), nullable=False),
        sa.Column("completed_at", sa.DateTime(timezone=True), nullable=True),
        sa.Column("failed_reason", sa.Text, nullable=True),
        # Snapshot of manifest sections hash — used by diff?since={run_id}
        sa.Column("manifest_snapshot_hash", sa.String(64), nullable=True),
        sa.Column("created_at", sa.DateTime(timezone=True), server_default=sa.func.now()),
    )
    op.create_index("ix_manifest_runs_project_id", "manifest_runs", ["project_id"])
    op.create_index("ix_manifest_runs_token_hash", "manifest_runs", ["token_hash"])
    op.create_index("ix_manifest_runs_expires_at", "manifest_runs", ["expires_at"])


def downgrade() -> None:
    op.drop_table("manifest_runs")
    op.execute("DROP TYPE IF EXISTS p2hs_manifest_run_status")
