"""
Migration: add compaction_in_progress / compaction_started_at columns.

Adds two nullable columns to hippo_conversations for partial-failure
recovery in the compaction pipeline:

  - compaction_in_progress  INTEGER  (0/1 flag, default 0)
  - compaction_started_at   TEXT     (ISO timestamp of last compaction start)

If a process crashes mid-compaction the flag is left set.  On the next
startup, ``recover_stale_compaction_flags()`` clears any flags older than
a configurable threshold so the next run proceeds normally.

Issue: hippo-hardening — edge cases for empty/long/concurrent compaction
"""

from __future__ import annotations

import logging

import aiosqlite

logger = logging.getLogger(__name__)

MIGRATION_NAME = "add_compaction_guard"
MIGRATION_VERSION = 5  # bumps from previous schema version


async def needs_migration(conn: aiosqlite.Connection) -> bool:
    """Check if the compaction_in_progress column already exists."""
    async with conn.execute("PRAGMA table_info(hippo_conversations)") as cur:
        columns = [row[1] async for row in cur]
    return "compaction_in_progress" not in columns


async def migrate(conn: aiosqlite.Connection) -> None:
    """Add compaction guard columns to hippo_conversations."""
    if not await needs_migration(conn):
        logger.info("Migration %s: already applied, skipping", MIGRATION_NAME)
        return

    logger.info(
        "Migration %s: adding compaction_in_progress / compaction_started_at",
        MIGRATION_NAME,
    )

    await conn.execute(
        "ALTER TABLE hippo_conversations "
        "ADD COLUMN compaction_in_progress INTEGER NOT NULL DEFAULT 0"
    )
    await conn.execute(
        "ALTER TABLE hippo_conversations "
        "ADD COLUMN compaction_started_at TEXT"
    )
    await conn.execute(
        """
        CREATE INDEX IF NOT EXISTS idx_hippo_conversations_compaction_in_progress
            ON hippo_conversations(compaction_in_progress)
            WHERE compaction_in_progress = 1
        """
    )

    # Update schema version in hippo_config
    try:
        await conn.execute(
            """
            INSERT INTO hippo_config (key, value, updated_at)
            VALUES ('schema_version', ?, strftime('%Y-%m-%dT%H:%M:%SZ', 'now'))
            ON CONFLICT(key) DO UPDATE SET
                value = excluded.value,
                updated_at = excluded.updated_at
            """,
            (str(MIGRATION_VERSION),),
        )
    except Exception:
        # hippo_config may not exist in older test DBs — not fatal
        pass

    await conn.commit()
    logger.info("Migration %s: complete", MIGRATION_NAME)
