#!/usr/bin/env python3
"""Mentor review state management.

Tracks the last reviewed git SHA so the cron job knows what diff to review.

Usage:
    mentor_state.py get          # print last_reviewed_sha (or '' if unset)
    mentor_state.py init         # initialize state to current HEAD (no-op if already set)
    mentor_state.py update       # set state to current HEAD
    mentor_state.py show         # print full state JSON
    mentor_state.py changed      # print changed .md files in REVIEW_SCOPE_DIRS since last review, one per line

The `changed` command is scoped to REVIEW_SCOPE_DIRS — the directories where
Dennis writes actual analysis (journals, trades, research, performance,
per-instrument notes). Infrastructure directories (00-methodology, 05-data,
07-calendar, 90-archive, _templates, _meta, _assets, scripts) are excluded
so the mentor doesn't review them.

To change the scope, edit REVIEW_SCOPE_DIRS below and mirror the change in
~/Obsidian-Macro/_meta/mentor-config.md for documentation.
"""
from __future__ import annotations

import argparse
import json
import subprocess
import sys
from datetime import datetime, timezone
from pathlib import Path

VAULT = Path("/home/rpi/Obsidian-Macro")
STATE = VAULT / "_meta" / "mentor-state.json"

# Analysis-only directories the mentor reviews. Anything outside this list
# (templates, methodology, data, calendar, archive, config, assets, scripts,
# top-level files) is treated as infrastructure and excluded.
REVIEW_SCOPE_DIRS = [
    "01-journal",      # daily journal entries
    "02-trades",       # per-trade folders (thesis, execution, mgmt, postmortem)
    "03-research",     # weekly, event, deep, lessons-learned
    "04-performance",  # NAV, attribution, monthly letters
    "06-universe",     # per-instrument notes (traded + monitored)
]


def current_head() -> str:
    return subprocess.check_output(
        ["git", "-C", str(VAULT), "rev-parse", "HEAD"], text=True
    ).strip()


def load_state() -> dict:
    if not STATE.exists():
        return {"last_reviewed_sha": "", "last_reviewed_at": "", "runs": 0}
    return json.loads(STATE.read_text())


def save_state(state: dict) -> None:
    STATE.parent.mkdir(parents=True, exist_ok=True)
    STATE.write_text(json.dumps(state, indent=2) + "\n")


def _list_changed_in_scope(since: str) -> list[str]:
    """Return .md paths changed since `since`, restricted to REVIEW_SCOPE_DIRS (recursive)."""
    if not since:
        print(
            "state not initialized — run `mentor_state.py init` first",
            file=sys.stderr,
        )
        return []
    result = subprocess.run(
        ["git", "-C", str(VAULT), "diff", "--name-only", since, "HEAD", "--"]
        + REVIEW_SCOPE_DIRS,
        capture_output=True,
        text=True,
        check=True,
    )
    return [line for line in result.stdout.splitlines() if line.endswith(".md")]


def cmd_get(_args) -> int:
    print(load_state().get("last_reviewed_sha", ""))
    return 0


def cmd_init(_args) -> int:
    state = load_state()
    if state.get("last_reviewed_sha"):
        print(f"already initialized: {state['last_reviewed_sha']}", file=sys.stderr)
        return 0
    head = current_head()
    state["last_reviewed_sha"] = head
    state["last_reviewed_at"] = datetime.now(timezone.utc).isoformat()
    state["runs"] = state.get("runs", 0)
    save_state(state)
    print(f"initialized: {head}")
    return 0


def cmd_update(_args) -> int:
    head = current_head()
    state = load_state()
    state["last_reviewed_sha"] = head
    state["last_reviewed_at"] = datetime.now(timezone.utc).isoformat()
    state["runs"] = state.get("runs", 0) + 1
    save_state(state)
    print(f"updated: {head}")
    return 0


def cmd_show(_args) -> int:
    print(json.dumps(load_state(), indent=2))
    return 0


def cmd_changed(_args) -> int:
    state = load_state()
    since = state.get("last_reviewed_sha", "")
    paths = _list_changed_in_scope(since)
    if paths:
        sys.stdout.write("\n".join(paths) + "\n")
    return 0


def main() -> int:
    p = argparse.ArgumentParser()
    sp = p.add_subparsers(dest="cmd", required=True)
    for c in ("get", "init", "update", "show", "changed"):
        sp.add_parser(c)
    args = p.parse_args()
    return {
        "get": cmd_get,
        "init": cmd_init,
        "update": cmd_update,
        "show": cmd_show,
        "changed": cmd_changed,
    }[args.cmd](args)


if __name__ == "__main__":
    sys.exit(main())