"""Tests for container configuration persistence store."""

import tempfile
from datetime import datetime
from pathlib import Path

import pytest

from gaol.models.container import ContainerConfig, NetworkConfig, NetworkMode
from gaol.store import ContainerStore, StoredContainer


class TestStoredContainer:
    """Tests for StoredContainer model."""

    def test_stored_container_creation(self) -> None:
        """Test creating a StoredContainer."""
        config = ContainerConfig(name="test", distro="trixie")
        now = datetime.now()
        stored = StoredContainer(
            config=config,
            container_id="abc123",
            runtime="docker",
            created_at=now,
            updated_at=now,
        )
        assert stored.config.name == "test"
        assert stored.container_id == "abc123"
        assert stored.runtime == "docker"
        assert stored.last_started_at is None

    def test_stored_container_with_started_at(self) -> None:
        """Test StoredContainer with last_started_at."""
        config = ContainerConfig(name="test", distro="trixie")
        now = datetime.now()
        stored = StoredContainer(
            config=config,
            runtime="docker",
            created_at=now,
            updated_at=now,
            last_started_at=now,
        )
        assert stored.last_started_at == now


class TestContainerStore:
    """Tests for ContainerStore class."""

    @pytest.fixture
    def temp_store(self) -> ContainerStore:
        """Create a temporary store for testing."""
        with tempfile.TemporaryDirectory() as tmpdir:
            yield ContainerStore(store_dir=Path(tmpdir))

    def test_save_and_get(self, temp_store: ContainerStore) -> None:
        """Test saving and retrieving a container config."""
        config = ContainerConfig(
            name="test-container",
            distro="trixie",
            profiles=["base"],
        )
        stored = temp_store.save(config, container_id="abc123", runtime="docker")

        assert stored.config.name == "test-container"
        assert stored.container_id == "abc123"
        assert stored.runtime == "docker"

        # Retrieve it
        retrieved = temp_store.get("test-container")
        assert retrieved is not None
        assert retrieved.config.name == "test-container"
        assert retrieved.container_id == "abc123"

    def test_get_nonexistent(self, temp_store: ContainerStore) -> None:
        """Test getting a container that doesn't exist."""
        result = temp_store.get("nonexistent")
        assert result is None

    def test_exists(self, temp_store: ContainerStore) -> None:
        """Test checking if a container exists."""
        config = ContainerConfig(name="test", distro="trixie")
        temp_store.save(config, runtime="docker")

        assert temp_store.exists("test")
        assert not temp_store.exists("nonexistent")

    def test_list_empty(self, temp_store: ContainerStore) -> None:
        """Test listing when store is empty."""
        result = temp_store.list()
        assert result == []

    def test_list_containers(self, temp_store: ContainerStore) -> None:
        """Test listing stored containers."""
        config1 = ContainerConfig(name="alpha", distro="trixie")
        config2 = ContainerConfig(name="beta", distro="bookworm")
        temp_store.save(config1, runtime="docker")
        temp_store.save(config2, runtime="nspawn")

        containers = temp_store.list()
        assert len(containers) == 2
        # Should be sorted by name
        assert containers[0].config.name == "alpha"
        assert containers[1].config.name == "beta"

    def test_delete(self, temp_store: ContainerStore) -> None:
        """Test deleting a container."""
        config = ContainerConfig(name="test", distro="trixie")
        temp_store.save(config, runtime="docker")

        assert temp_store.exists("test")
        result = temp_store.delete("test")
        assert result is True
        assert not temp_store.exists("test")

    def test_delete_nonexistent(self, temp_store: ContainerStore) -> None:
        """Test deleting a container that doesn't exist."""
        result = temp_store.delete("nonexistent")
        assert result is False

    def test_update_preserves_created_at(self, temp_store: ContainerStore) -> None:
        """Test that updating a container preserves created_at."""
        config = ContainerConfig(name="test", distro="trixie")
        stored1 = temp_store.save(config, runtime="docker")
        original_created = stored1.created_at

        # Update with new config
        config2 = ContainerConfig(name="test", distro="bookworm")
        stored2 = temp_store.save(config2, runtime="docker")

        assert stored2.created_at == original_created
        assert stored2.config.distro == "bookworm"

    def test_update_started(self, temp_store: ContainerStore) -> None:
        """Test updating last_started_at."""
        config = ContainerConfig(name="test", distro="trixie")
        temp_store.save(config, runtime="docker")

        stored = temp_store.get("test")
        assert stored is not None
        assert stored.last_started_at is None

        temp_store.update_started("test")

        stored = temp_store.get("test")
        assert stored is not None
        assert stored.last_started_at is not None

    def test_update_container_id(self, temp_store: ContainerStore) -> None:
        """Test updating container ID."""
        config = ContainerConfig(name="test", distro="trixie")
        temp_store.save(config, container_id="old123", runtime="docker")

        temp_store.update_container_id("test", "new456")

        stored = temp_store.get("test")
        assert stored is not None
        assert stored.container_id == "new456"

    def test_save_with_full_config(self, temp_store: ContainerStore) -> None:
        """Test saving a fully configured container."""
        config = ContainerConfig(
            name="full-test",
            distro="noble",
            profiles=["base", "tailscale"],
            network=NetworkConfig(
                mode=NetworkMode.BRIDGED,
                ports={8080: 80, 443: 443},
                hostname="mycontainer",
            ),
            volumes={"/host/data": "/container/data"},
            environment={"KEY": "value"},
            privileged=True,
        )
        temp_store.save(config, container_id="xyz789", runtime="nspawn")

        retrieved = temp_store.get("full-test")
        assert retrieved is not None
        assert retrieved.config.profiles == ["base", "tailscale"]
        assert retrieved.config.network.mode == NetworkMode.BRIDGED
        assert retrieved.config.network.ports == {8080: 80, 443: 443}
        assert retrieved.config.volumes == {"/host/data": "/container/data"}
        assert retrieved.config.privileged is True
