#!/usr/bin/env python3
"""
Genesis Stop State Flush (Layer 7 of Defense System)
====================================================
Stop hook that fires when a session ends (gracefully or not).
Performs a final state dump so the next session can recover.

This is a LAST RESORT backup. If all other hooks fail and the session
is dying, this captures whatever state is available.

Also handles API error detection: if the observability log shows
repeated 400 errors (thinking block corruption pattern), this
writes a crash report.
"""

import sys
import json
import os
import shutil
from datetime import datetime, timezone
from pathlib import Path

BACKUP_DIR = Path("/mnt/e/genesis-system/hive/session_backups")
RECOVERY_DIR = Path("/mnt/e/genesis-system/hive/session_recovery")
STATE_DIR = Path("/mnt/e/genesis-system/data/context_state")
EVENTS_DIR = Path("/mnt/e/genesis-system/data/observability")


def get_session_info() -> dict:
    """Gather all available session state."""
    info = {
        "timestamp": datetime.now(timezone.utc).isoformat(),
        "session_id": os.environ.get("CLAUDE_SESSION_ID", "unknown"),
        "agent_id": os.environ.get("CLAUDE_AGENT_ID", "primary"),
        "event": "session_stop",
    }

    # Read context state
    try:
        state_file = STATE_DIR / "current.json"
        if state_file.exists():
            with open(state_file, "r") as f:
                info["context_state"] = json.load(f)
    except Exception:
        pass

    # Read metrics
    try:
        metrics_file = EVENTS_DIR / "metrics.json"
        if metrics_file.exists():
            with open(metrics_file, "r") as f:
                info["metrics"] = json.load(f)
    except Exception:
        pass

    # Count compactions
    try:
        log_file = STATE_DIR / "compaction_log.jsonl"
        if log_file.exists():
            with open(log_file, "r") as f:
                info["total_compactions"] = sum(1 for _ in f)
    except Exception:
        pass

    # Check for error pattern (thinking block corruption)
    try:
        events_file = EVENTS_DIR / "events.jsonl"
        if events_file.exists():
            with open(events_file, "rb") as f:
                f.seek(0, 2)
                file_size = f.tell()
                read_size = min(file_size, 20000)
                f.seek(file_size - read_size)
                tail = f.read().decode("utf-8", errors="replace")

            error_count = tail.count("tool_failure")
            info["recent_error_count"] = error_count
            if error_count > 5:
                info["crash_suspected"] = True
                info["crash_type"] = "possible_thinking_block_corruption"
    except Exception:
        pass

    return info


def write_stop_state(info: dict):
    """Write session stop state."""
    BACKUP_DIR.mkdir(parents=True, exist_ok=True)
    RECOVERY_DIR.mkdir(parents=True, exist_ok=True)

    session_id = info.get("session_id", "unknown")
    timestamp = datetime.now(timezone.utc).strftime("%Y%m%d_%H%M%S")

    # Write JSON backup
    try:
        backup_file = BACKUP_DIR / f"stop_{session_id[:8]}_{timestamp}.json"
        with open(backup_file, "w") as f:
            json.dump(info, f, indent=2)
    except Exception:
        pass

    # Update LATEST.md with stop info
    try:
        recovery_file = RECOVERY_DIR / "LATEST.md"
        existing = ""
        if recovery_file.exists():
            with open(recovery_file, "r") as f:
                existing = f.read()

        stop_section = f"""
## Session Stop Event
**Time**: {info.get('timestamp', 'unknown')}
**Session**: {session_id}
**Context at stop**: {info.get('context_state', {}).get('used_percentage', '?')}%
**Compactions**: {info.get('total_compactions', '?')}
**Crash suspected**: {info.get('crash_suspected', False)}
**Crash type**: {info.get('crash_type', 'none')}
"""
        # Prepend stop info to existing recovery doc
        with open(recovery_file, "w") as f:
            if existing:
                # Insert after first header
                lines = existing.split("\n")
                insert_idx = 2  # After "# Session Recovery State"
                lines.insert(insert_idx, stop_section)
                f.write("\n".join(lines))
            else:
                f.write(f"# Session Recovery State\n{stop_section}\n")
    except Exception:
        pass


def main():
    try:
        hook_input = json.loads(sys.stdin.read())
    except (json.JSONDecodeError, Exception):
        hook_input = {}

    info = get_session_info()
    write_stop_state(info)

    # Log to observability
    try:
        EVENTS_DIR.mkdir(parents=True, exist_ok=True)
        event = {
            "timestamp": info["timestamp"],
            "event_type": "session_death_flush",
            "session_id": info["session_id"],
            "context_pct": info.get("context_state", {}).get("used_percentage", 0),
            "crash_suspected": info.get("crash_suspected", False),
        }
        events_file = EVENTS_DIR / "events.jsonl"
        with open(events_file, "a") as f:
            f.write(json.dumps(event) + "\n")
    except Exception:
        pass

    print(json.dumps({}))


if __name__ == "__main__":
    main()
