"""Container configuration persistence store."""

from __future__ import annotations

from datetime import datetime
from pathlib import Path

import yaml
from pydantic import BaseModel

from gaol.config import get_config_dir
from gaol.models.container import ContainerConfig


class StoredContainer(BaseModel):
    """Stored container configuration with metadata."""

    config: ContainerConfig
    container_id: str | None = None
    runtime: str
    created_at: datetime
    updated_at: datetime
    last_started_at: datetime | None = None
    setup_done: bool = False  # True after profiles have been applied


class ContainerStore:
    """Persistent storage for container configurations."""

    def __init__(self, store_dir: Path | None = None) -> None:
        """Initialize the container store.

        Args:
            store_dir: Directory to store container configs. Defaults to
                       ~/.config/gaol/containers/
        """
        if store_dir is None:
            store_dir = get_config_dir() / "containers"
        self._store_dir = store_dir
        self._store_dir.mkdir(parents=True, exist_ok=True)

    def _get_path(self, name: str) -> Path:
        """Get the path for a container config file."""
        return self._store_dir / f"{name}.yaml"

    def save(
        self,
        config: ContainerConfig,
        container_id: str | None = None,
        runtime: str | None = None,
    ) -> StoredContainer:
        """Save a container configuration.

        Args:
            config: Container configuration to save
            container_id: Runtime-specific container ID
            runtime: Runtime used (defaults to config.runtime)

        Returns:
            The stored container record
        """
        path = self._get_path(config.name)
        now = datetime.now()

        # Check if already exists to preserve created_at
        existing = self.get(config.name)
        if existing:
            stored = StoredContainer(
                config=config,
                container_id=container_id or existing.container_id,
                runtime=runtime or existing.runtime,
                created_at=existing.created_at,
                updated_at=now,
                last_started_at=existing.last_started_at,
            )
        else:
            stored = StoredContainer(
                config=config,
                container_id=container_id,
                runtime=runtime or config.runtime,
                created_at=now,
                updated_at=now,
            )

        # Write to file
        data = stored.model_dump(mode="json")
        path.write_text(yaml.dump(data, default_flow_style=False, sort_keys=False))
        return stored

    def get(self, name: str) -> StoredContainer | None:
        """Get a stored container configuration.

        Args:
            name: Container name

        Returns:
            StoredContainer if found, None otherwise
        """
        path = self._get_path(name)
        if not path.exists():
            return None

        data = yaml.safe_load(path.read_text())
        return StoredContainer(**data)

    def list(self) -> list[StoredContainer]:
        """List all stored container configurations.

        Returns:
            List of stored containers
        """
        containers = []
        for path in self._store_dir.glob("*.yaml"):
            try:
                data = yaml.safe_load(path.read_text())
                containers.append(StoredContainer(**data))
            except Exception:
                # Skip invalid files
                continue
        return sorted(containers, key=lambda c: c.config.name)

    def delete(self, name: str) -> bool:
        """Delete a stored container configuration.

        Args:
            name: Container name

        Returns:
            True if deleted, False if not found
        """
        path = self._get_path(name)
        if path.exists():
            path.unlink()
            return True
        return False

    def exists(self, name: str) -> bool:
        """Check if a container configuration exists.

        Args:
            name: Container name

        Returns:
            True if exists
        """
        return self._get_path(name).exists()

    def update_started(self, name: str) -> None:
        """Update the last_started_at timestamp.

        Args:
            name: Container name
        """
        stored = self.get(name)
        if stored:
            path = self._get_path(name)
            stored.last_started_at = datetime.now()
            stored.updated_at = datetime.now()
            data = stored.model_dump(mode="json")
            path.write_text(yaml.dump(data, default_flow_style=False, sort_keys=False))

    def update_container_id(self, name: str, container_id: str) -> None:
        """Update the container ID.

        Args:
            name: Container name
            container_id: New container ID
        """
        stored = self.get(name)
        if stored:
            path = self._get_path(name)
            stored.container_id = container_id
            stored.updated_at = datetime.now()
            data = stored.model_dump(mode="json")
            path.write_text(yaml.dump(data, default_flow_style=False, sort_keys=False))

    def update_setup_done(self, name: str, done: bool = True) -> None:
        """Mark setup as complete for a container.

        Args:
            name: Container name
            done: Whether setup is complete
        """
        stored = self.get(name)
        if stored:
            path = self._get_path(name)
            stored.setup_done = done
            stored.updated_at = datetime.now()
            data = stored.model_dump(mode="json")
            path.write_text(yaml.dump(data, default_flow_style=False, sort_keys=False))


# Global store instance
_store: ContainerStore | None = None


def get_container_store() -> ContainerStore:
    """Get the global container store instance."""
    global _store
    if _store is None:
        _store = ContainerStore()
    return _store
