"""Migrate FTS5 table to use porter stemming tokenizer.

Usage:
    python -m pulse.brain.index.fts_stemming          # migrate
    python -m pulse.brain.index.fts_stemming --test    # test stemming
"""
from __future__ import annotations
import logging, time

log = logging.getLogger("pulse.fts_stemming")

KNOWLEDGE_TABLES = (
    "lessons", "failures", "patterns", "facts",
    "evidence", "intents", "decisions", "private",
)


def migrate_fts_to_porter() -> dict:
    """Drop and recreate knowledge_fts with porter stemming, re-index all rows."""
    from pulse.core.brain_db import get_conn
    conn = get_conn()

    # Check current tokenizer
    try:
        info = conn.execute(
            "SELECT sql FROM sqlite_master WHERE name='knowledge_fts'"
        ).fetchone()
        current_sql = info[0] if info else ""
        if "porter" in current_sql.lower():
            log.info("FTS already uses porter stemming, skipping migration")
            return {"status": "already_migrated"}
    except Exception:
        pass

    start = time.time()
    old_count = conn.execute("SELECT COUNT(*) FROM knowledge_fts").fetchone()[0]
    log.info("Migrating FTS5 to porter stemming (%d existing entries)", old_count)

    with conn:
        # Drop triggers first (they reference the old FTS table)
        for tbl in KNOWLEDGE_TABLES:
            for op in ("insert", "delete", "update"):
                conn.execute(f"DROP TRIGGER IF EXISTS fts_{op}_{tbl}")

        # Drop old FTS table
        conn.execute("DROP TABLE IF EXISTS knowledge_fts")

        # Recreate with porter tokenizer
        conn.execute("""
        CREATE VIRTUAL TABLE knowledge_fts USING fts5(
            item_id UNINDEXED, content, title, domain, agent, table_name,
            tokenize = 'porter unicode61'
        );
        """)

        # Re-create triggers
        for tbl in KNOWLEDGE_TABLES:
            conn.execute(f"""
            CREATE TRIGGER IF NOT EXISTS fts_insert_{tbl} AFTER INSERT ON {tbl} BEGIN
                INSERT INTO knowledge_fts(item_id, content, title, domain, agent, table_name)
                VALUES (NEW.id, NEW.content, NEW.title, NEW.domain, NEW.agent, '{tbl}');
            END;""")
            conn.execute(f"""
            CREATE TRIGGER IF NOT EXISTS fts_delete_{tbl} AFTER DELETE ON {tbl} BEGIN
                DELETE FROM knowledge_fts WHERE item_id = OLD.id AND table_name = '{tbl}';
            END;""")
            conn.execute(f"""
            CREATE TRIGGER IF NOT EXISTS fts_update_{tbl}
            AFTER UPDATE OF content, title, domain ON {tbl} BEGIN
                DELETE FROM knowledge_fts WHERE item_id = OLD.id AND table_name = '{tbl}';
                INSERT INTO knowledge_fts(item_id, content, title, domain, agent, table_name)
                VALUES (NEW.id, NEW.content, NEW.title, NEW.domain, NEW.agent, '{tbl}');
            END;""")

        # Re-index all existing rows
        total = 0
        for tbl in KNOWLEDGE_TABLES:
            try:
                has_title = True
                try:
                    conn.execute(f"SELECT title FROM {tbl} LIMIT 1")
                except Exception:
                    has_title = False
                has_agent = True
                try:
                    conn.execute(f"SELECT agent FROM {tbl} LIMIT 1")
                except Exception:
                    has_agent = False
                t_col = "title" if has_title else "''"
                a_col = "agent" if has_agent else "'unknown'"
                count = conn.execute(
                    f"INSERT INTO knowledge_fts (item_id, content, title, domain, agent, table_name) "
                    f"SELECT id, content, {t_col}, domain, {a_col}, '{tbl}' FROM {tbl}"
                ).rowcount
                total += count
                log.info("%s: %d rows indexed", tbl, count)
            except Exception as e:
                log.warning("Failed to index %s: %s", tbl, e)

    elapsed = time.time() - start
    log.info("FTS migration complete: %d rows in %.1fs (was %d)", total, elapsed, old_count)
    return {"status": "migrated", "rows": total, "elapsed_s": round(elapsed, 1)}


def test_stemming():
    """Test that porter stemming works correctly."""
    from pulse.core.brain_db import get_conn
    conn = get_conn()
    tests = [
        ("configure", "configuration"),
        ("running", "run"),
        ("embedded", "embedding"),
        ("failures", "failure"),
    ]
    results = []
    for stem_a, stem_b in tests:
        # Search for stem_a, see if items containing stem_b appear
        rows_a = conn.execute(
            "SELECT COUNT(*) FROM knowledge_fts WHERE knowledge_fts MATCH ?",
            (stem_a,)
        ).fetchone()[0]
        rows_b = conn.execute(
            "SELECT COUNT(*) FROM knowledge_fts WHERE knowledge_fts MATCH ?",
            (stem_b,)
        ).fetchone()[0]
        results.append({"query_a": stem_a, "hits_a": rows_a,
                        "query_b": stem_b, "hits_b": rows_b,
                        "stem_match": rows_a == rows_b})
        log.info("%s -> %d hits, %s -> %d hits, match=%s",
                 stem_a, rows_a, stem_b, rows_b, rows_a == rows_b)
    return results


if __name__ == "__main__":
    import argparse
    logging.basicConfig(level=logging.INFO, format="%(asctime)s %(message)s")

    parser = argparse.ArgumentParser()
    parser.add_argument("--test", action="store_true")
    args = parser.parse_args()

    if args.test:
        test_stemming()
    else:
        migrate_fts_to_porter()
