#!/usr/bin/env python3
"""
Memory Compact Monthly — Move 1a of Brain Maintenance

Summarizes daily logs older than 30 days into monthly summaries.
Archives raw daily logs to memory/archive/.

Usage:
    python3 scripts/memory-compact-monthly.py [--dry-run] [--days 30]

Flow:
1. Scan memory/YYYY-MM-DD.md files
2. Find files older than --days (default 30)
3. Group by month
4. For each month, create/append to memory/monthly/YYYY-MM.md with summary
5. Move raw files to memory/archive/

The summary extracts:
- Key decisions (lines containing "decision", "decided", "chose", "approved")
- Outcomes (lines containing "complete", "shipped", "launched", "deployed")
- Learnings (lines containing "learning", "mistake", "rule", "lesson")
- Unresolved items (lines containing "blocked", "waiting", "TODO", "pending")
- Handover notes (sections titled HANDOVER)
"""

import os
import re
import shutil
import sys
from datetime import datetime, timedelta
from pathlib import Path
from collections import defaultdict

MEMORY_DIR = Path(os.environ.get("MEMORY_DIR", os.path.expanduser("~/.openclaw/workspace/memory")))
MONTHLY_DIR = MEMORY_DIR / "monthly"
ARCHIVE_DIR = MEMORY_DIR / "archive"

# Keywords for extraction
DECISION_KEYWORDS = ["decision", "decided", "chose", "approved", "going with", "picked", "selected"]
OUTCOME_KEYWORDS = ["complete", "completed", "shipped", "launched", "deployed", "done", "finished", "delivered"]
LEARNING_KEYWORDS = ["learning", "mistake", "rule", "lesson", "failed", "error", "fix", "never again"]
UNRESOLVED_KEYWORDS = ["blocked", "waiting", "todo", "pending", "need to", "still need", "unresolved", "open question"]
HANDOVER_PATTERN = re.compile(r"^#+\s*handover", re.IGNORECASE)


def find_daily_logs(days_threshold: int) -> list[tuple[Path, datetime]]:
    """Find daily log files older than days_threshold."""
    cutoff = datetime.now() - timedelta(days=days_threshold)
    pattern = re.compile(r"^(\d{4}-\d{2}-\d{2})\.md$")
    results = []

    for f in MEMORY_DIR.iterdir():
        match = pattern.match(f.name)
        if match:
            try:
                file_date = datetime.strptime(match.group(1), "%Y-%m-%d")
                if file_date < cutoff:
                    results.append((f, file_date))
            except ValueError:
                continue

    return sorted(results, key=lambda x: x[1])


def extract_sections(content: str) -> dict[str, list[str]]:
    """Extract key sections from a daily log."""
    sections = {
        "decisions": [],
        "outcomes": [],
        "learnings": [],
        "unresolved": [],
        "handover": [],
    }

    lines = content.split("\n")
    in_handover = False

    for line in lines:
        stripped = line.strip()
        if not stripped:
            continue

        lower = stripped.lower()

        # Check for handover section
        if HANDOVER_PATTERN.match(stripped):
            in_handover = True
            continue

        if in_handover:
            if stripped.startswith("#"):
                in_handover = False
            else:
                sections["handover"].append(stripped)
                continue

        # Classify line
        if any(kw in lower for kw in DECISION_KEYWORDS):
            sections["decisions"].append(stripped)
        elif any(kw in lower for kw in OUTCOME_KEYWORDS):
            sections["outcomes"].append(stripped)
        elif any(kw in lower for kw in LEARNING_KEYWORDS):
            sections["learnings"].append(stripped)
        elif any(kw in lower for kw in UNRESOLVED_KEYWORDS):
            sections["unresolved"].append(stripped)

    return sections


def generate_monthly_summary(month: str, daily_entries: list[tuple[str, dict]]) -> str:
    """Generate a monthly summary from extracted daily sections."""
    lines = [f"# Monthly Summary: {month}\n"]
    lines.append(f"*Auto-generated from {len(daily_entries)} daily logs*\n")

    # Aggregate all sections
    all_decisions = []
    all_outcomes = []
    all_learnings = []
    all_unresolved = []

    for date_str, sections in daily_entries:
        for d in sections["decisions"]:
            all_decisions.append(f"- [{date_str}] {d}")
        for o in sections["outcomes"]:
            all_outcomes.append(f"- [{date_str}] {o}")
        for l in sections["learnings"]:
            all_learnings.append(f"- [{date_str}] {l}")
        for u in sections["unresolved"]:
            all_unresolved.append(f"- [{date_str}] {u}")

    if all_decisions:
        lines.append("\n## Decisions")
        lines.extend(all_decisions)

    if all_outcomes:
        lines.append("\n## Outcomes")
        lines.extend(all_outcomes)

    if all_learnings:
        lines.append("\n## Learnings")
        lines.extend(all_learnings)

    if all_unresolved:
        lines.append("\n## Unresolved (at time of logging)")
        lines.extend(all_unresolved)

    lines.append(f"\n---\n*Compacted on {datetime.now().strftime('%Y-%m-%d')}*")
    return "\n".join(lines)


def main():
    dry_run = "--dry-run" in sys.argv
    days = 30
    for i, arg in enumerate(sys.argv):
        if arg == "--days" and i + 1 < len(sys.argv):
            days = int(sys.argv[i + 1])

    # Ensure directories exist
    MONTHLY_DIR.mkdir(parents=True, exist_ok=True)
    ARCHIVE_DIR.mkdir(parents=True, exist_ok=True)

    # Find old daily logs
    old_logs = find_daily_logs(days)
    if not old_logs:
        print(f"No daily logs older than {days} days found.")
        return

    print(f"Found {len(old_logs)} daily logs older than {days} days")

    # Group by month
    by_month: dict[str, list[tuple[str, Path]]] = defaultdict(list)
    for path, date in old_logs:
        month_key = date.strftime("%Y-%m")
        date_str = date.strftime("%Y-%m-%d")
        by_month[month_key].append((date_str, path))

    # Process each month
    for month, entries in sorted(by_month.items()):
        print(f"\n📅 {month}: {len(entries)} daily logs")

        # Extract sections from each daily log
        daily_sections = []
        for date_str, path in entries:
            content = path.read_text(encoding="utf-8")
            sections = extract_sections(content)
            daily_sections.append((date_str, sections))
            total = sum(len(v) for v in sections.values())
            print(f"  {date_str}: {total} extracted items")

        # Generate summary
        summary = generate_monthly_summary(month, daily_sections)
        summary_path = MONTHLY_DIR / f"{month}.md"

        if dry_run:
            print(f"  [DRY RUN] Would write summary to {summary_path}")
            print(f"  [DRY RUN] Would archive {len(entries)} files to {ARCHIVE_DIR}/")
        else:
            # Write or append summary
            if summary_path.exists():
                existing = summary_path.read_text(encoding="utf-8")
                summary_path.write_text(existing + "\n\n" + summary, encoding="utf-8")
                print(f"  ✅ Appended to {summary_path}")
            else:
                summary_path.write_text(summary, encoding="utf-8")
                print(f"  ✅ Created {summary_path}")

            # Archive raw files
            for date_str, path in entries:
                dest = ARCHIVE_DIR / path.name
                shutil.move(str(path), str(dest))
                print(f"  📦 Archived {path.name}")

    print(f"\n{'[DRY RUN] ' if dry_run else ''}Done. Processed {len(old_logs)} daily logs across {len(by_month)} months.")


if __name__ == "__main__":
    main()
