"""
Persistence utilities for GSD-RLM sessions.

Provides JSON file operations with error handling and atomic writes.
"""

import json
import tempfile
from pathlib import Path
from typing import Any, Dict, Optional
from datetime import datetime
import shutil


def save_json(
    data: Dict[str, Any],
    path: Path,
    indent: int = 2,
    ensure_ascii: bool = False,
) -> None:
    """Save data to JSON file with atomic write.

    Uses atomic write pattern: write to temp file, then rename.
    This prevents corruption from partial writes.

    Args:
        data: Data to save
        path: Target file path
        indent: JSON indentation
        ensure_ascii: Whether to escape non-ASCII
    """
    path = Path(path)
    path.parent.mkdir(parents=True, exist_ok=True)

    # Write to temp file first
    temp_path = path.with_suffix(path.suffix + ".tmp")

    try:
        with open(temp_path, "w", encoding="utf-8") as f:
            json.dump(data, f, indent=indent, ensure_ascii=ensure_ascii)

        # Atomic rename
        shutil.move(str(temp_path), str(path))

    except Exception as e:
        # Clean up temp file on error
        if temp_path.exists():
            temp_path.unlink()
        raise


def load_json(
    path: Path,
    default: Optional[Dict[str, Any]] = None,
) -> Optional[Dict[str, Any]]:
    """Load data from JSON file.

    Args:
        path: File path
        default: Default value if file doesn't exist

    Returns:
        Loaded data or default
    """
    path = Path(path)
    if not path.exists():
        return default

    try:
        with open(path, "r", encoding="utf-8") as f:
            return json.load(f)
    except json.JSONDecodeError:
        return default


class SessionFileManager:
    """Manages session-related files."""

    def __init__(self, base_dir: Path):
        """
        Initialize file manager.

        Args:
            base_dir: Base directory for all session files
        """
        self.base_dir = Path(base_dir)
        self.sessions_dir = self.base_dir / "sessions"
        self.exports_dir = self.base_dir / "exports"

    def setup(self) -> None:
        """Create directory structure."""
        self.sessions_dir.mkdir(parents=True, exist_ok=True)
        self.exports_dir.mkdir(parents=True, exist_ok=True)

    def get_session_path(self, session_id: str) -> Path:
        """Get path to session file."""
        safe_id = self._sanitize_id(session_id)
        return self.sessions_dir / f"{safe_id}.json"

    def get_export_path(self, session_id: str, format: str = "md") -> Path:
        """Get path for session export."""
        safe_id = self._sanitize_id(session_id)
        timestamp = datetime.utcnow().strftime("%Y%m%d-%H%M%S")
        return self.exports_dir / f"{safe_id}-{timestamp}.{format}"

    def export_session_markdown(
        self,
        session_data: Dict[str, Any],
        output_path: Optional[Path] = None,
    ) -> Path:
        """Export session to Markdown format.

        Args:
            session_data: Session data to export
            output_path: Optional output path

        Returns:
            Path to exported file
        """
        if output_path is None:
            output_path = self.get_export_path(
                session_data.get("session_id", "unknown"), "md"
            )

        lines = [
            f"# Session: {session_data.get('session_id', 'Unknown')}",
            "",
            f"**Agent:** {session_data.get('agent_name', 'Unknown')}",
            f"**Created:** {session_data.get('created_at', 'Unknown')}",
            f"**Updated:** {session_data.get('updated_at', 'Unknown')}",
            "",
            "## Messages",
            "",
        ]

        for msg in session_data.get("messages", []):
            role = msg.get("role", "unknown")
            content = msg.get("content", "")
            lines.append(f"### {role.title()}")
            lines.append("```")
            lines.append(content)
            lines.append("```")
            lines.append("")

        if session_data.get("task_outputs"):
            lines.extend(
                [
                    "## Task Outputs",
                    "",
                ]
            )
            for task in session_data["task_outputs"]:
                status = "✓" if task.get("success") else "✗"
                lines.append(f"### {status} {task.get('task', 'Unknown')}")
                if task.get("error"):
                    lines.append(f"Error: {task['error']}")
                lines.append("")

        output_path.write_text("\n".join(lines), encoding="utf-8")
        return output_path

    def cleanup_old_sessions(self, max_age_days: int = 30) -> int:
        """Remove sessions older than max_age_days.

        Args:
            max_age_days: Maximum age in days

        Returns:
            Number of sessions removed
        """
        import time

        removed = 0
        cutoff = time.time() - (max_age_days * 86400)

        for session_file in self.sessions_dir.glob("*.json"):
            if session_file.stat().st_mtime < cutoff:
                session_file.unlink()
                removed += 1

        return removed

    def _sanitize_id(self, id: str) -> str:
        """Sanitize ID for filesystem."""
        return "".join(c if c.isalnum() or c in "-_" else "_" for c in id)
