"""Stop hook: after every assistant turn, regenerate memory/recent_turns.md from
this session's transcript, keeping only the most recent 10 turns.

Crash recovery only. Never raises -- a broken hook must not break the session.
"""
import json
import os
import sys
from datetime import datetime, timezone
from pathlib import Path

MAX_TURNS = 10
MAX_USER_CHARS = 1500
MAX_ASSISTANT_CHARS = 3000
SKIP_PREFIXES = (
    '<command-name>',
    '<local-command-stdout>',
    '<local-command-caveat>',
)
OUT_PATH = Path(r'C:\Users\lirse\soccer\soccer\memory\recent_turns.md')


def sanitize_cwd(cwd):
    return ''.join('-' if c in ':\\/' else c for c in cwd)


def find_transcript(data):
    for key in ('transcript_path', 'transcriptPath'):
        p = data.get(key)
        if p and Path(p).exists():
            return Path(p)
    session_id = data.get('session_id') or data.get('sessionId')
    cwd = data.get('cwd') or os.getcwd()
    if session_id:
        proj = sanitize_cwd(cwd)
        candidate = Path.home() / '.claude' / 'projects' / proj / f'{session_id}.jsonl'
        if candidate.exists():
            return candidate
    return None


def load_turns(path):
    turns = []
    current = None
    with path.open('r', encoding='utf-8') as f:
        for line in f:
            line = line.strip()
            if not line:
                continue
            try:
                d = json.loads(line)
            except json.JSONDecodeError:
                continue
            if d.get('isSidechain') or d.get('isMeta'):
                continue
            t = d.get('type')
            msg = d.get('message') or {}
            content = msg.get('content')
            if t == 'user' and isinstance(content, str) and content.strip():
                # Slash-command plumbing (/model, /clear, ...) arrives as ordinary
                # user records without isMeta. Keeping them burns the 10 turn slots
                # on noise, which is the whole point of the file.
                if content.lstrip().startswith(SKIP_PREFIXES):
                    continue
                if current:
                    turns.append(current)
                current = {'ts': d.get('timestamp', ''), 'user': content.strip(), 'assistant': []}
            elif t == 'assistant' and current is not None and isinstance(content, list):
                for block in content:
                    if isinstance(block, dict) and block.get('type') == 'text':
                        txt = (block.get('text') or '').strip()
                        if txt:
                            current['assistant'].append(txt)
    if current:
        turns.append(current)
    return turns[-MAX_TURNS:]


def truncate(s, n):
    s = s.strip()
    if len(s) <= n:
        return s
    return s[:n].rstrip() + '... [truncated]'


def render(turns, session_id):
    now = datetime.now(timezone.utc).strftime('%Y-%m-%d %H:%M:%S UTC')
    lines = [
        '# Recent conversation turns (crash-recovery log)',
        '',
        f'Auto-generated after every assistant turn by .claude/hooks/save_recent_turns.py. '
        f'Last updated: {now}. Session: {session_id or "unknown"}.',
        f'Holds only the most recent {MAX_TURNS} turns -- read this at the start of a new '
        f'session if the prior one ended without a normal handoff.',
        '',
    ]
    for i, turn in enumerate(turns, 1):
        lines.append(f'## Turn {i} -- {turn["ts"]}')
        lines.append('')
        lines.append('**User:**')
        lines.append(truncate(turn['user'], MAX_USER_CHARS))
        lines.append('')
        if turn['assistant']:
            lines.append('**Assistant:**')
            lines.append(truncate('\n\n'.join(turn['assistant']), MAX_ASSISTANT_CHARS))
        else:
            lines.append('**Assistant:** _(no text response captured -- tool-only turn)_')
        lines.append('')
    return '\n'.join(lines) + '\n'


def main():
    try:
        raw = sys.stdin.buffer.read().decode('utf-8-sig')
        data = json.loads(raw) if raw.strip() else {}
    except Exception:
        data = {}

    transcript = find_transcript(data)
    if not transcript:
        return

    try:
        turns = load_turns(transcript)
    except Exception:
        return
    if not turns:
        return

    session_id = data.get('session_id') or data.get('sessionId')
    text = render(turns, session_id)

    try:
        OUT_PATH.parent.mkdir(parents=True, exist_ok=True)
        tmp = OUT_PATH.with_suffix('.md.tmp')
        tmp.write_text(text, encoding='utf-8')
        os.replace(tmp, OUT_PATH)
    except Exception:
        pass


if __name__ == '__main__':
    try:
        main()
    except Exception:
        pass
