
import re
from pathlib import Path
from datetime import datetime

SCRIPT_DIR = Path(__file__).resolve().parent
ROOT_DIR = SCRIPT_DIR.parent.parent.parent

import sys
if str(ROOT_DIR) not in sys.path:
    sys.path.insert(0, str(ROOT_DIR))

BRAIN_FILES = [
    ROOT_DIR / "Hippocampus" / "Lessons" / "auto_lessons.md",
    ROOT_DIR / "Hippocampus" / "Failures" / "auto_fails.md",
    ROOT_DIR / "Hippocampus" / "Patterns" / "auto_patterns.md",
]
ARCHIVE_DIR = ROOT_DIR / "Hippocampus" / "archive"

# Brain files are STORAGE for search/retrieval. Boot briefing already selects
# a working-memory subset. 200 entries keeps quality knowledge while preventing
# unbounded growth. Sort by quality (salience * confidence) not just recency.
MAX_ENTRIES_PER_FILE = 200


def _extract_quality(entry_text: str) -> float:
    """Extract quality score from entry metadata (salience * confidence).

    Falls back to 0.5 if metadata is missing (old entries without salience).
    """
    salience = 1.0
    confidence = 0.5
    sal_match = re.search(r'\*\*Salience:\*\*\s*([\d.]+)', entry_text)
    if sal_match:
        try:
            salience = float(sal_match.group(1))
        except ValueError:
            pass
    conf_match = re.search(r'\*\*Confidence:\*\*\s*([\d.]+)', entry_text)
    if conf_match:
        try:
            confidence = float(conf_match.group(1))
        except ValueError:
            pass
    return salience * confidence


def prune_file(path: Path, max_entries: int = MAX_ENTRIES_PER_FILE):
    if not path.exists():
        return

    content = path.read_text(encoding="utf-8")
    # Split by ## (sections), keep the header
    sections = re.split(r'\n(?=## )', content)
    if len(sections) <= max_entries + 1:  # Header + entries — keep all if under limit
        return

    header = sections[0]
    entries = sections[1:]

    # Extract date, quality, and keywords for each entry
    entry_data = []
    for i, entry in enumerate(entries):
        date_match = re.search(r'\*\*Date:\*\* (\d{4}-\d{2}-\d{2})', entry)
        date = date_match.group(1) if date_match else "0000-00-00"
        quality = _extract_quality(entry)
        entry_data.append({
            "index": i,
            "content": entry,
            "date": date,
            "quality": quality,
        })

    # Sort by quality (descending), then recency (descending) as tiebreaker
    entry_data.sort(key=lambda x: (x["quality"], x["date"], x["index"]), reverse=True)

    # Keep top N highest-quality entries
    to_keep_data = entry_data[:max_entries]
    to_archive_data = entry_data[max_entries:]

    # Sort back to original order for the file
    to_keep_data.sort(key=lambda x: x["index"])
    to_archive_data.sort(key=lambda x: x["index"])

    # Each entry starts with "## " (from the split). Rejoin with "\n" to restore newlines.
    if to_keep_data:
        kept_content = header + "\n" + "\n".join(d["content"] for d in to_keep_data)
    else:
        kept_content = header
    path.write_text(kept_content, encoding="utf-8")

    # Archive the rest
    if to_archive_data:
        ARCHIVE_DIR.mkdir(parents=True, exist_ok=True)
        archive_path = ARCHIVE_DIR / f"archived_{path.name}"
        timestamp = datetime.now().isoformat()
        with open(archive_path, "a", encoding="utf-8") as f:
            f.write(f"\n\n# Archived from {path.name} on {timestamp}\n")
            f.write("".join(d["content"] for d in to_archive_data))
        print(f"[PRUNE] Archived {len(to_archive_data)} entries from {path.name}")


def run():
    print(f"[PRUNE] Starting brain pruning at {datetime.now().isoformat()}")
    for path in BRAIN_FILES:
        try:
            prune_file(path)
        except Exception as e:
            print(f"[PRUNE] Error pruning {path.name}: {e}")
    print("[PRUNE] Pruning complete.")

if __name__ == "__main__":
    run()
