from __future__ import annotations

import json
from datetime import datetime, timezone
from pathlib import Path
from typing import Any, Dict, List, Optional


class RecoveryManager:
    """Capture file and config snapshots for remediation transactions."""

    def __init__(self, root: str | Path):
        self.root = Path(root)
        self.root.mkdir(parents=True, exist_ok=True)

    @staticmethod
    def _utc_now() -> str:
        return datetime.now(timezone.utc).isoformat(timespec="milliseconds")

    def capture_snapshot(
        self,
        transaction_id: str,
        affected_paths: List[str],
        metadata: Optional[Dict[str, Any]] = None,
    ) -> Dict[str, Any]:
        snapshot_dir = self.root / transaction_id
        snapshot_dir.mkdir(parents=True, exist_ok=True)

        manifest = {
            "transaction_id": transaction_id,
            "timestamp": self._utc_now(),
            "affected_files": [],
            "metadata": metadata or {},
        }

        for item in affected_paths:
            path = Path(item)
            file_payload = {
                "path": str(path),
                "exists": path.exists(),
                "size": path.stat().st_size if path.exists() else 0,
                "last_modified": datetime.fromtimestamp(path.stat().st_mtime, tz=timezone.utc).isoformat() if path.exists() else None,
            }
            manifest["affected_files"].append(file_payload)

        manifest_path = snapshot_dir / "manifest.json"
        manifest_path.write_text(json.dumps(manifest, indent=2, sort_keys=True), encoding="utf-8")

        return {
            "transaction_id": transaction_id,
            "snapshot_dir": str(snapshot_dir),
            "affected_files": manifest["affected_files"],
            "manifest": manifest,
        }
