"""Snapshot (.agtrace) file read/write."""
from __future__ import annotations

import gzip
import json
from datetime import datetime, timezone
from pathlib import Path
from typing import Optional

SNAPSHOT_DIR = Path.home() / ".agentradar" / "snapshots"
MAX_SNAPSHOT_SIZE = 50 * 1024 * 1024  # 50 MB


def _ensure_dir():
    SNAPSHOT_DIR.mkdir(parents=True, exist_ok=True)


def save_snapshot(run_state: dict, name: str = "snapshot", output_dir: Optional[Path] = None) -> Path:
    """Save a run snapshot as a .agtrace file."""
    _ensure_dir()
    timestamp = datetime.now(timezone.utc).strftime("%Y%m%d_%H%M%S")
    safe_name = "".join(c if c.isalnum() or c in "-_" else "_" for c in name)
    filename = f"{safe_name}_{timestamp}.agtrace"

    target_dir = Path(output_dir) if output_dir else SNAPSHOT_DIR
    target_dir.mkdir(parents=True, exist_ok=True)
    path = target_dir / filename

    payload = {
        "version": "1.0.0",
        "created_at": datetime.now(timezone.utc).isoformat(),
        "run": run_state,
    }
    data = json.dumps(payload, default=str).encode("utf-8")

    if len(data) > MAX_SNAPSHOT_SIZE:
        print(f"agentradar: snapshot exceeds 50MB limit, truncating.")
        # Trim steps to stay within limit
        run_state_trimmed = run_state.copy()
        steps = run_state_trimmed.get("steps", [])
        while len(data) > MAX_SNAPSHOT_SIZE and steps:
            steps = steps[len(steps) // 2:]
            run_state_trimmed["steps"] = steps
            payload["run"] = run_state_trimmed
            data = json.dumps(payload, default=str).encode("utf-8")

    with gzip.open(str(path), "wb") as f:
        f.write(data)

    return path


def load_snapshot(name_or_path: str) -> dict:
    """Load a .agtrace snapshot file."""
    path = Path(name_or_path)
    if not path.exists():
        # Try in snapshot dir
        path = SNAPSHOT_DIR / name_or_path
        if not path.exists():
            # Try adding extension
            path = SNAPSHOT_DIR / f"{name_or_path}.agtrace"
    if not path.exists():
        raise FileNotFoundError(f"Snapshot not found: {name_or_path}")

    with gzip.open(str(path), "rb") as f:
        data = json.loads(f.read().decode("utf-8"))
    return data


def list_snapshots() -> list[dict]:
    """List all saved snapshots."""
    _ensure_dir()
    snapshots = []
    for path in sorted(SNAPSHOT_DIR.glob("*.agtrace"), key=lambda p: p.stat().st_mtime, reverse=True):
        try:
            stat = path.stat()
            snapshots.append({
                "name": path.stem,
                "filename": path.name,
                "path": str(path),
                "size_bytes": stat.st_size,
                "modified": datetime.fromtimestamp(stat.st_mtime, tz=timezone.utc).isoformat(),
            })
        except Exception:
            pass
    return snapshots


def delete_snapshot(name: str) -> bool:
    path = SNAPSHOT_DIR / f"{name}.agtrace"
    if path.exists():
        path.unlink()
        return True
    return False
