#!/usr/bin/env python3
"""Tests for config_template.py — issue #696"""
import os
import sys
import tempfile
import pytest
from pathlib import Path

# Add parent dir for import
sys.path.insert(0, str(Path(__file__).resolve().parent.parent / "scripts"))
from config_template import ConfigTemplate, _deep_merge, _get_dotted, _diff_dicts, _validate_config


@pytest.fixture
def tmp_config_dir(tmp_path):
    """Create a temp config dir with base + overlay files."""
    import yaml
    base = {
        "model": {"name": "base-model", "temperature": 0.7},
        "cron": {"enabled": False, "interval": 300},
        "display": {"colors": True},
    }
    overlay = {
        "model": {"temperature": 0.9},
        "cron": {"enabled": True},
        "logging": {"level": "DEBUG"},
    }
    with open(tmp_path / "base.yaml", "w") as f:
        yaml.dump(base, f)
    with open(tmp_path / "test.overlay.yaml", "w") as f:
        yaml.dump(overlay, f)
    return tmp_path


class TestDeepMerge:
    def test_overlay_wins(self):
        base = {"a": 1, "b": 2}
        overlay = {"b": 99}
        result = _deep_merge(base, overlay)
        assert result == {"a": 1, "b": 99}

    def test_deep_merge_nested(self):
        base = {"model": {"name": "x", "temp": 0.7}}
        overlay = {"model": {"temp": 0.9}}
        result = _deep_merge(base, overlay)
        assert result["model"]["name"] == "x"
        assert result["model"]["temp"] == 0.9

    def test_new_keys_added(self):
        base = {"a": 1}
        overlay = {"b": 2}
        result = _deep_merge(base, overlay)
        assert result == {"a": 1, "b": 2}

    def test_originals_unchanged(self):
        base = {"a": {"inner": 1}}
        overlay = {"a": {"inner": 99}}
        _deep_merge(base, overlay)
        assert base["a"]["inner"] == 1


class TestDottedAccess:
    def test_simple_key(self):
        assert _get_dotted({"a": 1}, "a") == 1

    def test_nested_key(self):
        assert _get_dotted({"a": {"b": {"c": 42}}}, "a.b.c") == 42

    def test_missing_key_returns_default(self):
        assert _get_dotted({"a": 1}, "x", "fallback") == "fallback"

    def test_partial_path(self):
        assert _get_dotted({"a": 1}, "a.b.c", None) is None


class TestDiff:
    def test_no_diff(self):
        assert _diff_dicts({"a": 1}, {"a": 1}) == []

    def test_changed_value(self):
        diffs = _diff_dicts({"a": 1}, {"a": 2})
        assert len(diffs) == 1
        assert diffs[0]["type"] == "changed"

    def test_added_key(self):
        diffs = _diff_dicts({"a": 1}, {"a": 1, "b": 2})
        added = [d for d in diffs if d["type"] == "added_in_overlay"]
        assert len(added) == 1
        assert added[0]["key"] == "b"


class TestValidation:
    def test_valid_config(self):
        config = {"model": {"name": "x"}, "provider": {"name": "y"}}
        assert _validate_config(config) == []

    def test_missing_model(self):
        warnings = _validate_config({"provider": {}})
        assert any("model" in w for w in warnings)


class TestConfigTemplate:
    def test_load(self, tmp_config_dir):
        t = ConfigTemplate(str(tmp_config_dir))
        merged = t.load("test")
        assert merged["model"]["name"] == "base-model"
        assert merged["model"]["temperature"] == 0.9
        assert merged["cron"]["enabled"] is True
        assert merged["logging"]["level"] == "DEBUG"

    def test_get_dotted(self, tmp_config_dir):
        t = ConfigTemplate(str(tmp_config_dir))
        t.load("test")
        assert t.get("model.temperature") == 0.9
        assert t.get("nonexistent", "default") == "default"

    def test_diff(self, tmp_config_dir):
        t = ConfigTemplate(str(tmp_config_dir))
        t.load("test")
        diffs = t.diff()
        assert len(diffs) > 0

    def test_unknown_env_raises(self, tmp_config_dir):
        t = ConfigTemplate(str(tmp_config_dir))
        with pytest.raises(ValueError, match="Unknown environment"):
            t.load("nonexistent")

    def test_list_environments(self):
        envs = ConfigTemplate.list_environments()
        assert "dev" in envs
        assert "prod" in envs
        assert "cron" in envs
        assert "gateway" in envs
