"""Add pipeline_runs table for dashboard analytics.

Revision ID: add_pipeline_runs
Revises: add_concept_rdf_columns
Create Date: 2026-03-03 12:00:00.000000

"""

from __future__ import annotations

from typing import Sequence

import sqlalchemy as sa
from alembic import op

from pycharter.db.migrations.schema_helper import get_schema

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


def upgrade() -> None:
    """Create pipeline_runs table."""
    bind = op.get_bind()
    schema = get_schema(bind)
    is_sqlite = schema is None
    datetime_default = sa.text("CURRENT_TIMESTAMP") if is_sqlite else sa.text("now()")

    op.create_table(
        "pipeline_runs",
        sa.Column("id", sa.UUID(as_uuid=True), nullable=False),
        sa.Column("run_id", sa.String(length=8), nullable=False),
        sa.Column("pipeline_name", sa.String(length=255), nullable=True),
        sa.Column(
            "status",
            sa.String(length=20),
            nullable=False,
            server_default="success",
        ),
        # Row metrics
        sa.Column("rows_extracted", sa.Integer(), nullable=False, server_default="0"),
        sa.Column("rows_transformed", sa.Integer(), nullable=False, server_default="0"),
        sa.Column("rows_loaded", sa.Integer(), nullable=False, server_default="0"),
        sa.Column("rows_failed", sa.Integer(), nullable=False, server_default="0"),
        sa.Column("rows_quarantined", sa.Integer(), nullable=False, server_default="0"),
        sa.Column(
            "batches_processed", sa.Integer(), nullable=False, server_default="0"
        ),
        # Timing
        sa.Column("started_at", sa.DateTime(timezone=True), nullable=True),
        sa.Column("completed_at", sa.DateTime(timezone=True), nullable=True),
        sa.Column("duration_seconds", sa.Float(), nullable=True),
        # Quality
        sa.Column("quality_score", sa.Float(), nullable=True),
        sa.Column("quality_passed", sa.Boolean(), nullable=True),
        # Pipeline context
        sa.Column("extractor_type", sa.String(length=50), nullable=True),
        sa.Column("loader_type", sa.String(length=50), nullable=True),
        sa.Column(
            "trigger",
            sa.String(length=20),
            nullable=False,
            server_default="api",
        ),
        # Detail storage (JSON)
        sa.Column("errors", sa.JSON(), nullable=True),
        sa.Column("batch_results", sa.JSON(), nullable=True),
        sa.Column("config_snapshot", sa.JSON(), nullable=True),
        # Audit
        sa.Column(
            "created_at",
            sa.DateTime(timezone=True),
            server_default=datetime_default,
            nullable=True,
        ),
        sa.Column(
            "updated_at",
            sa.DateTime(timezone=True),
            server_default=datetime_default,
            nullable=True,
        ),
        sa.Column("created_by", sa.String(length=255), nullable=True),
        sa.PrimaryKeyConstraint("id"),
        sa.UniqueConstraint("run_id"),
        schema=schema,
    )

    # Create indexes for common query patterns
    op.create_index(
        "ix_pipeline_runs_run_id",
        "pipeline_runs",
        ["run_id"],
        schema=schema,
    )
    op.create_index(
        "ix_pipeline_runs_pipeline_name",
        "pipeline_runs",
        ["pipeline_name"],
        schema=schema,
    )
    op.create_index(
        "ix_pipeline_runs_status",
        "pipeline_runs",
        ["status"],
        schema=schema,
    )
    op.create_index(
        "ix_pipeline_runs_started_at",
        "pipeline_runs",
        ["started_at"],
        schema=schema,
    )


def downgrade() -> None:
    """Drop pipeline_runs table."""
    bind = op.get_bind()
    schema = get_schema(bind)

    op.drop_index(
        "ix_pipeline_runs_started_at",
        table_name="pipeline_runs",
        schema=schema,
    )
    op.drop_index(
        "ix_pipeline_runs_status",
        table_name="pipeline_runs",
        schema=schema,
    )
    op.drop_index(
        "ix_pipeline_runs_pipeline_name",
        table_name="pipeline_runs",
        schema=schema,
    )
    op.drop_index(
        "ix_pipeline_runs_run_id",
        table_name="pipeline_runs",
        schema=schema,
    )
    op.drop_table("pipeline_runs", schema=schema)
