"""Persistence for update policies and history."""

from __future__ import annotations

import os
import stat
from pathlib import Path

import yaml

from gaol.config import get_data_dir
from gaol.update.models import (
    UpdateHistory,
    UpdatePolicy,
    UpdateResult,
    UpdateStatus,
)


def _get_update_dir() -> Path:
    """Get the update data directory."""
    return get_data_dir() / "update"


class UpdateStore:
    """Persistent storage for update policies and history.

    Directory structure:
        ~/.local/share/gaol/update/
            policies/
                {container_name}.yaml
            history/
                {container_name}.yaml
    """

    def __init__(self, store_dir: Path | None = None) -> None:
        """Initialize the store."""
        self._store_dir = store_dir or _get_update_dir()
        self._policies_dir = self._store_dir / "policies"
        self._history_dir = self._store_dir / "history"

    def _ensure_dirs(self) -> None:
        """Ensure store directories exist with proper permissions."""
        for dir_path in [self._store_dir, self._policies_dir, self._history_dir]:
            dir_path.mkdir(parents=True, exist_ok=True)
            os.chmod(dir_path, stat.S_IRWXU)  # 700

    def _write_yaml(self, path: Path, data: dict) -> None:
        """Write YAML with atomic write and proper permissions."""
        self._ensure_dirs()
        temp_path = path.with_suffix(".tmp")
        with open(temp_path, "w") as f:
            yaml.dump(data, f, default_flow_style=False)
        os.chmod(temp_path, stat.S_IRUSR | stat.S_IWUSR)  # 600
        temp_path.rename(path)

    def _read_yaml(self, path: Path) -> dict | None:
        """Read YAML file if it exists."""
        if not path.exists():
            return None
        with open(path) as f:
            return yaml.safe_load(f) or {}

    # Policy operations

    def save_policy(self, policy: UpdatePolicy) -> None:
        """Save or update an update policy."""
        path = self._policies_dir / f"{policy.container_name}.yaml"
        self._write_yaml(path, policy.model_dump(mode="json"))

    def get_policy(self, container_name: str) -> UpdatePolicy | None:
        """Get update policy for a container."""
        path = self._policies_dir / f"{container_name}.yaml"
        data = self._read_yaml(path)
        if data is None:
            return None
        return UpdatePolicy.model_validate(data)

    def delete_policy(self, container_name: str) -> bool:
        """Delete a policy. Returns True if deleted."""
        path = self._policies_dir / f"{container_name}.yaml"
        if path.exists():
            path.unlink()
            return True
        return False

    def list_policies(self) -> list[UpdatePolicy]:
        """List all update policies."""
        if not self._policies_dir.exists():
            return []

        policies = []
        for path in self._policies_dir.glob("*.yaml"):
            try:
                data = self._read_yaml(path)
                if data:
                    policies.append(UpdatePolicy.model_validate(data))
            except Exception:
                continue
        return policies

    def policy_exists(self, container_name: str) -> bool:
        """Check if a policy exists."""
        path = self._policies_dir / f"{container_name}.yaml"
        return path.exists()

    # History operations

    def save_history(self, history: UpdateHistory) -> None:
        """Save update history for a container."""
        path = self._history_dir / f"{history.container_name}.yaml"
        self._write_yaml(path, history.model_dump(mode="json"))

    def get_history(self, container_name: str) -> UpdateHistory:
        """Get update history for a container (creates if not exists)."""
        path = self._history_dir / f"{container_name}.yaml"
        data = self._read_yaml(path)
        if data is None:
            return UpdateHistory(container_name=container_name)
        return UpdateHistory.model_validate(data)

    def append_result(self, result: UpdateResult) -> None:
        """Append an update result to history."""
        history = self.get_history(result.container_name)
        history.add_result(result)
        self.save_history(history)

    def delete_history(self, container_name: str) -> bool:
        """Delete history for a container. Returns True if deleted."""
        path = self._history_dir / f"{container_name}.yaml"
        if path.exists():
            path.unlink()
            return True
        return False

    def list_histories(self) -> list[UpdateHistory]:
        """List all update histories."""
        if not self._history_dir.exists():
            return []

        histories = []
        for path in self._history_dir.glob("*.yaml"):
            try:
                data = self._read_yaml(path)
                if data:
                    histories.append(UpdateHistory.model_validate(data))
            except Exception:
                continue
        return histories


# Global instance
_store: UpdateStore | None = None


def get_update_store() -> UpdateStore:
    """Get the global update store instance."""
    global _store
    if _store is None:
        _store = UpdateStore()
    return _store
