"""Add repo_indexes and indexed_files tables for repository indexing.

Revision ID: m7_001_repo_indexing_tables
Revises: m6_003_async_jobs_table
Create Date: 2026-03-06 00:00:00

"""

from collections.abc import Sequence

import sqlalchemy as sa
from alembic import op

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


def upgrade() -> None:
    """Create the repo_indexes and indexed_files tables."""
    op.create_table(
        "repo_indexes",
        sa.Column("index_id", sa.String(26), primary_key=True),
        sa.Column("resource_id", sa.String(26), nullable=False, unique=True),
        sa.Column("file_count", sa.Integer(), nullable=False, server_default="0"),
        sa.Column("token_estimate", sa.Integer(), nullable=False, server_default="0"),
        sa.Column(
            "primary_language",
            sa.String(50),
            nullable=False,
            server_default="unknown",
        ),
        sa.Column("status", sa.String(20), nullable=False, server_default="pending"),
        sa.Column("error_message", sa.Text(), nullable=True),
        sa.Column("indexed_at", sa.String(40), nullable=False),
        sa.Column("created_at", sa.String(40), nullable=False),
        sa.CheckConstraint(
            "status IN ('pending', 'indexing', 'ready', 'stale', 'error')",
            name="ck_repo_indexes_status",
        ),
    )
    # resource_id already has unique=True which creates an implicit unique
    # index — no redundant explicit index needed.
    op.create_index("ix_repo_indexes_status", "repo_indexes", ["status"])

    op.create_table(
        "indexed_files",
        sa.Column("index_id", sa.String(26), nullable=False, primary_key=True),
        sa.Column("path", sa.String(1024), nullable=False, primary_key=True),
        sa.Column("content_hash", sa.String(64), nullable=False),
        sa.Column("token_count", sa.Integer(), nullable=False, server_default="0"),
        sa.Column("size_bytes", sa.Integer(), nullable=False, server_default="0"),
        sa.Column("language", sa.String(50), nullable=False, server_default="unknown"),
        sa.Column("last_modified", sa.String(40), nullable=False),
        sa.ForeignKeyConstraint(
            ["index_id"],
            ["repo_indexes.index_id"],
            ondelete="CASCADE",
        ),
    )
    # index_id is the first column in the composite PK — SQLite already uses
    # it for lookups; an additional single-column index is redundant.
    # Note: FK ON DELETE CASCADE declared above is inactive without
    # PRAGMA foreign_keys=ON; manual child-row deletion handles this.
    op.create_index("ix_indexed_files_language", "indexed_files", ["language"])


def downgrade() -> None:
    """Drop the indexed_files and repo_indexes tables."""
    op.drop_index("ix_indexed_files_language", table_name="indexed_files")
    op.drop_table("indexed_files")
    op.drop_index("ix_repo_indexes_status", table_name="repo_indexes")
    op.drop_table("repo_indexes")
