"""
Tests for decnet.config — Pydantic models, save/load/clear state.
Covers the uncovered lines: validators, save_state, load_state, clear_state.
"""
import pytest

import decnet.config as config_module
from decnet.config import (
    DeckyConfig,
    DecnetConfig,
    save_state,
    load_state,
    clear_state,
)


# ---------------------------------------------------------------------------
# DeckyConfig validator
# ---------------------------------------------------------------------------

class TestDeckyConfig:
    def _base(self, **kwargs):
        defaults = dict(
            name="decky-01", ip="192.168.1.10", services=["ssh"],
            distro="debian", base_image="debian", hostname="host-01",
        )
        defaults.update(kwargs)
        return defaults

    def test_valid_decky(self):
        d = DeckyConfig(**self._base())
        assert d.name == "decky-01"

    def test_empty_services_raises(self):
        with pytest.raises(Exception, match="at least 1 item"):
            DeckyConfig(**self._base(services=[]))

    def test_multiple_services_ok(self):
        d = DeckyConfig(**self._base(services=["ssh", "smb", "rdp"]))
        assert len(d.services) == 3


# ---------------------------------------------------------------------------
# DecnetConfig validator
# ---------------------------------------------------------------------------

class TestDecnetConfig:
    def _base_decky(self):
        return DeckyConfig(
            name="d", ip="10.0.0.2", services=["ssh"],
            distro="debian", base_image="debian", hostname="h",
        )

    def test_valid_config(self):
        cfg = DecnetConfig(
            mode="unihost", interface="eth0",
            subnet="10.0.0.0/24", gateway="10.0.0.1",
            deckies=[self._base_decky()],
        )
        assert cfg.mode == "unihost"

    def test_log_file_field(self):
        cfg = DecnetConfig(
            mode="unihost", interface="eth0",
            subnet="10.0.0.0/24", gateway="10.0.0.1",
            deckies=[self._base_decky()],
            log_file="/var/log/decnet/decnet.log",
        )
        assert cfg.log_file == "/var/log/decnet/decnet.log"

    def test_log_file_defaults_to_none(self):
        cfg = DecnetConfig(
            mode="unihost", interface="eth0",
            subnet="10.0.0.0/24", gateway="10.0.0.1",
            deckies=[self._base_decky()],
        )
        assert cfg.log_file is None


# ---------------------------------------------------------------------------
# save_state / load_state / clear_state
# ---------------------------------------------------------------------------

@pytest.fixture(autouse=True)
def patch_state_file(tmp_path, monkeypatch):
    monkeypatch.setattr(config_module, "STATE_FILE", tmp_path / "decnet-state.json")


def _sample_config():
    return DecnetConfig(
        mode="unihost", interface="eth0",
        subnet="192.168.1.0/24", gateway="192.168.1.1",
        deckies=[
            DeckyConfig(
                name="decky-01", ip="192.168.1.10", services=["ssh"],
                distro="debian", base_image="debian", hostname="host-01",
            )
        ],
    )


def test_save_and_load_state(tmp_path):
    cfg = _sample_config()
    compose = tmp_path / "docker-compose.yml"
    save_state(cfg, compose)

    result = load_state()
    assert result is not None
    loaded_cfg, loaded_compose = result
    assert loaded_cfg.mode == "unihost"
    assert loaded_cfg.deckies[0].name == "decky-01"
    assert loaded_compose == compose


def test_load_state_returns_none_when_missing(tmp_path, monkeypatch):
    monkeypatch.setattr(config_module, "STATE_FILE", tmp_path / "nonexistent.json")
    assert load_state() is None


def test_clear_state(tmp_path):
    cfg = _sample_config()
    save_state(cfg, tmp_path / "compose.yml")
    assert config_module.STATE_FILE.exists()

    clear_state()
    assert not config_module.STATE_FILE.exists()


def test_clear_state_noop_when_missing(tmp_path, monkeypatch):
    monkeypatch.setattr(config_module, "STATE_FILE", tmp_path / "nonexistent.json")
    clear_state()  # should not raise


def test_state_roundtrip_preserves_all_fields(tmp_path):
    cfg = _sample_config()
    cfg.deckies[0].archetype = "workstation"
    cfg.deckies[0].mutate_interval = 45
    compose = tmp_path / "compose.yml"
    save_state(cfg, compose)

    loaded_cfg, _ = load_state()
    assert loaded_cfg.deckies[0].archetype == "workstation"
    assert loaded_cfg.deckies[0].mutate_interval == 45
