#!/usr/bin/env python3
# Copyright (c) 2026 PULSE Contributors. Proprietary. All rights reserved.
"""
Fact Backfill: Extract declarative facts from existing capture logs.

Designed for swarm parallelism: each worker gets a chunk index.
  python fact_backfill.py --chunk 0 --total 10
  python fact_backfill.py --all  (single-threaded, processes everything)

Dependencies: Python stdlib + fact_parser + fact_store (Law 4)
"""

import os
import re
import sys
from pathlib import Path

SCRIPT_DIR = Path(__file__).resolve().parent
ROOT_DIR = SCRIPT_DIR.parent.parent
if str(ROOT_DIR) not in sys.path:
    sys.path.insert(0, str(ROOT_DIR))

from pulse.brain.fact_parser import parse_facts
from pulse.brain.fact_store import store_facts

STATE_DIR = ROOT_DIR / "state"
CAPTURE_LOGS = [
    STATE_DIR / "pulse_captured_claude.log",
    STATE_DIR / "pulse_captured_gemini.log",
    STATE_DIR / "pulse_captured_codex.log",
]

# Signed line format: [timestamp] ROLE: content | SIG: signature
LINE_PATTERN = re.compile(r"^\[(.*?)\] (USER|CLAUDE|GEMINI|CODEX|ASSISTANT): (.*)$")


def _parse_interactions(lines: list) -> list:
    """Reconstruct user/agent interaction pairs from raw log lines."""
    interactions = []
    current_user = None
    current_agent = []

    for line in lines:
        line = line.strip()
        if not line or " | SIG: " not in line:
            continue
        content_part = line.rsplit(" | SIG: ", 1)[0]
        m = LINE_PATTERN.match(content_part)
        if not m:
            continue
        _, role, content = m.groups()
        if role == "USER":
            if current_user and current_agent:
                interactions.append((current_user, "\n".join(current_agent)))
            current_user = content
            current_agent = []
        elif role in ("CLAUDE", "GEMINI", "CODEX", "ASSISTANT"):
            if current_user:
                current_agent.append(content)

    # Flush last interaction
    if current_user and current_agent:
        interactions.append((current_user, "\n".join(current_agent)))

    return interactions


def backfill_chunk(chunk_idx: int, total_chunks: int, verbose: bool = False) -> dict:
    """Process one chunk of capture logs. Returns stats."""
    stats = {"interactions": 0, "facts_extracted": 0, "facts_stored": 0}

    for log_path in CAPTURE_LOGS:
        if not log_path.exists():
            continue
        with open(log_path, "r", encoding="utf-8", errors="replace") as f:
            all_lines = f.readlines()

        total_lines = len(all_lines)
        chunk_size = total_lines // total_chunks
        start = chunk_idx * chunk_size
        end = start + chunk_size if chunk_idx < total_chunks - 1 else total_lines
        chunk_lines = all_lines[start:end]

        if verbose:
            print(f"[BACKFILL] {log_path.name}: lines {start}-{end} ({len(chunk_lines)} lines)")

        interactions = _parse_interactions(chunk_lines)
        stats["interactions"] += len(interactions)

        for user_text, agent_text in interactions:
            combined = f"{user_text}\n{agent_text}"
            facts = parse_facts(combined)
            for f in facts:
                f["backfilled"] = True
                f.setdefault("temporal", "historical")
            stats["facts_extracted"] += len(facts)
            if facts:
                written = store_facts(facts, source=f"backfill_{log_path.stem}")
                stats["facts_stored"] += written

    return stats


def backfill_all(verbose: bool = False) -> dict:
    """Process all capture logs (single-threaded)."""
    return backfill_chunk(0, 1, verbose=verbose)


if __name__ == "__main__":
    v = "--verbose" in sys.argv

    if "--all" in sys.argv:
        print("[BACKFILL] Processing all capture logs...")
        result = backfill_all(verbose=v)
        print(f"[BACKFILL] Done: {result['interactions']} interactions, "
              f"{result['facts_extracted']} extracted, {result['facts_stored']} stored")
        sys.exit(0)

    if "--chunk" in sys.argv and "--total" in sys.argv:
        chunk = int(sys.argv[sys.argv.index("--chunk") + 1])
        total = int(sys.argv[sys.argv.index("--total") + 1])
        print(f"[BACKFILL] Chunk {chunk}/{total}...")
        result = backfill_chunk(chunk, total, verbose=v)
        print(f"[BACKFILL] Chunk {chunk} done: {result['interactions']} interactions, "
              f"{result['facts_extracted']} extracted, {result['facts_stored']} stored")
        sys.exit(0)

    print("Usage: python fact_backfill.py --all | --chunk N --total M [--verbose]")
