#!/usr/bin/env python3
"""Session Handoff Summary — Stop Hook

Extracts key information from the session transcript and writes a structured
summary to the Claude memory directory so the next session can pick up context.

Usage (as Stop hook):
  Invoked automatically when a Claude Code session ends.
  Reads $TRANSCRIPT from the environment.

The output file is written to the Claude project memory directory, auto-detected
from the current working directory.
"""

import os
import re
import sys
from datetime import datetime
from pathlib import Path


def _memory_dir() -> Path:
    """Auto-detect the Claude memory directory for this project."""
    cwd = os.getcwd()
    slug = cwd.replace("/", "-").lstrip("-")
    return Path.home() / ".claude" / "projects" / slug / "memory"


OUTPUT_FILE = _memory_dir() / "last-session.md"


def extract_commits(transcript: str) -> list[str]:
    commits = []
    for m in re.finditer(r'\[(?:master|main|HEAD)[^\]]*\s+([a-f0-9]{7,})\]\s+(.+)', transcript):
        commits.append(f"`{m.group(1)}` -- {m.group(2).strip()}")
    return commits


def extract_files_changed(transcript: str) -> list[str]:
    files = set()
    for m in re.finditer(r'(?:src|app|lib|tests?|scripts|docs|backend|frontend)/[\w/.-]+\.\w+', transcript):
        files.add(m.group(0))
    return sorted(files)[:20]


def extract_tests_run(transcript: str) -> list[str]:
    results = []
    for m in re.finditer(r'(\d+ passed(?:,\s*\d+ (?:failed|warnings?|errors?|skipped|deselected))*)', transcript):
        results.append(f"pytest: {m.group(1)}")
    for m in re.finditer(r'Tests?\s+(\d+\s+passed\s*(?:\(\d+\))?)', transcript):
        results.append(f"vitest: {m.group(1)}")
    for m in re.finditer(r'(PASS|ok)\s+\S+\s+[\d.]+s', transcript):
        results.append(f"go/jest: {m.group(0)[:80]}")
    return results


def extract_errors(transcript: str) -> list[str]:
    errors = []
    seen = set()
    patterns = [
        r'((?:NameError|TypeError|AttributeError|ImportError|ValueError|KeyError):\s*.{10,80})',
        r'(HTTP\s+(?:4\d\d|5\d\d)\s+.{5,60})',
        r'(BLOCKED:\s*.{10,80})',
        r'(FAILED\s+.{10,80})',
    ]
    for pat in patterns:
        for m in re.finditer(pat, transcript):
            msg = m.group(1).strip()[:100]
            key = msg[:40]
            if key not in seen:
                seen.add(key)
                errors.append(msg)
    return errors[:10]


def extract_backlog_activity(transcript: str) -> list[str]:
    activity = []
    for m in re.finditer(r'((?:Added|Transitioned|Promoted):\s*SR-[\d-]+\s*[^\n]{0,80})', transcript):
        activity.append(m.group(1).strip())
    return activity


def extract_version_info(transcript: str) -> str | None:
    for m in re.finditer(r'Bumping version:\s*([\d.]+)\s*->\s*([\d.]+)', transcript):
        return f"{m.group(1)} -> {m.group(2)}"
    return None


def build_summary(transcript: str) -> str:
    now = datetime.now()
    commits = extract_commits(transcript)
    files = extract_files_changed(transcript)
    tests = extract_tests_run(transcript)
    errors = extract_errors(transcript)
    backlog = extract_backlog_activity(transcript)
    version = extract_version_info(transcript)

    lines = [
        "# Last Session Summary",
        "",
        f"**Date**: {now.strftime('%Y-%m-%d %H:%M')}",
        "**Auto-generated by session_handoff.py Stop hook**",
        "",
    ]

    if version:
        lines += ["## Version", f"- {version}", ""]
    if backlog:
        lines += ["## Backlog Activity"] + [f"- {b}" for b in backlog] + [""]
    if commits:
        lines += ["## Commits"] + [f"- {c}" for c in commits] + [""]
    if files:
        lines += ["## Files Touched"] + [f"- `{f}`" for f in files] + [""]
    if tests:
        lines += ["## Test Results"] + [f"- {t}" for t in tests] + [""]
    if errors:
        lines += ["## Errors Encountered"] + [f"- {e}" for e in errors] + [""]
    if not any([commits, files, tests, backlog]):
        lines += ["_No significant code activity detected in this session._", ""]

    return "\n".join(lines)


def main() -> int:
    transcript = os.environ.get("TRANSCRIPT", "")
    if not transcript:
        return 0

    summary = build_summary(transcript)
    output = _memory_dir() / "last-session.md"
    output.parent.mkdir(parents=True, exist_ok=True)
    output.write_text(summary, encoding="utf-8")
    print(f"Session summary written to {output}", file=sys.stderr)
    return 0


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