"""Formalize columns/tables added directly to DB without Alembic migrations.

These were applied manually to the live tenant_internal schema and must now
be captured so run_tenant_migrations.py picks them up for new tenants.

Columns:
  - tickets.is_starred       BOOLEAN DEFAULT FALSE
  - tickets.draft_html       TEXT nullable
  - addons_products.billing_active  BOOLEAN DEFAULT TRUE NOT NULL
  - audit_log.user_id        INTEGER nullable

Table:
  - ai_usage_log             (per-tenant AI call log)

Revision ID: infra001
Revises: pmcat001
Create Date: 2026-05-04
"""
from alembic import op
import sqlalchemy as sa
from sqlalchemy import text

revision = 'infra001'
down_revision = 'pmcat001'
branch_labels = None
depends_on = None


def _column_exists(conn, table, column):
    """Return True if column already exists in the current search_path schema."""
    result = conn.execute(
        text(
            "SELECT 1 FROM information_schema.columns "
            "WHERE table_name = :t AND column_name = :c"
        ),
        {"t": table, "c": column},
    ).fetchone()
    return result is not None


def _table_exists(conn, table):
    """Return True if table already exists in the current search_path schema."""
    result = conn.execute(
        text(
            "SELECT 1 FROM information_schema.tables "
            "WHERE table_name = :t"
        ),
        {"t": table},
    ).fetchone()
    return result is not None


def upgrade():
    conn = op.get_bind()

    # --- tickets.is_starred ---
    if not _column_exists(conn, "tickets", "is_starred"):
        op.add_column(
            "tickets",
            sa.Column("is_starred", sa.Boolean(), nullable=False, server_default="false"),
        )

    # --- tickets.draft_html ---
    if not _column_exists(conn, "tickets", "draft_html"):
        op.add_column(
            "tickets",
            sa.Column("draft_html", sa.Text(), nullable=True),
        )

    # --- addons_products.billing_active ---
    if not _column_exists(conn, "addons_products", "billing_active"):
        op.add_column(
            "addons_products",
            sa.Column(
                "billing_active",
                sa.Boolean(),
                nullable=False,
                server_default="true",
            ),
        )

    # --- audit_log.user_id ---
    if not _column_exists(conn, "audit_log", "user_id"):
        op.add_column(
            "audit_log",
            sa.Column("user_id", sa.Integer(), nullable=True),
        )

    # --- ai_usage_log table ---
    if not _table_exists(conn, "ai_usage_log"):
        op.create_table(
            "ai_usage_log",
            sa.Column("id", sa.Integer(), autoincrement=True, nullable=False),
            sa.Column("call_type", sa.String(20), nullable=False),
            sa.Column("model_used", sa.String(100), nullable=False),
            sa.Column("tokens_used", sa.Integer(), nullable=False, server_default="0"),
            sa.Column(
                "used_own_key", sa.Boolean(), nullable=False, server_default="false"
            ),
            sa.Column("created_at", sa.DateTime(), nullable=False),
            sa.PrimaryKeyConstraint("id"),
        )


def downgrade():
    conn = op.get_bind()

    if _table_exists(conn, "ai_usage_log"):
        op.drop_table("ai_usage_log")

    if _column_exists(conn, "audit_log", "user_id"):
        op.drop_column("audit_log", "user_id")

    if _column_exists(conn, "addons_products", "billing_active"):
        op.drop_column("addons_products", "billing_active")

    if _column_exists(conn, "tickets", "draft_html"):
        op.drop_column("tickets", "draft_html")

    if _column_exists(conn, "tickets", "is_starred"):
        op.drop_column("tickets", "is_starred")
