"""Tests for config loading and profile resolution."""

from __future__ import annotations

from pathlib import Path

import pytest

from sb_scout.config import (
    BUILTIN_DEFAULTS,
    LoadedConfig,
    _flatten_section,
    load_config,
    resolve_settings,
)


class TestFlattenSection:
    def test_top_level_passthrough(self):
        assert _flatten_section({"top": 10, "format": "markdown"}) == {
            "top": 10,
            "format": "markdown",
        }

    def test_filters_promoted(self):
        result = _flatten_section({"filters": {"ecc_only": True, "price_cap": 80}})
        assert result == {"ecc_only": True, "price_cap": 80}

    def test_bonuses_renamed(self):
        result = _flatten_section({"bonuses": {"inic": 0.20, "gpu": 0.25}})
        assert result == {"inic_bonus": 0.20, "gpu_bonus": 0.25}

    def test_weights_renamed(self):
        result = _flatten_section({
            "weights": {"cpu_rank_compute": 0.80, "overall": "0.5,0.3,0.2"},
        })
        assert result == {
            "cpu_rank_compute_weight": 0.80,
            "overall_weights": "0.5,0.3,0.2",
        }

    def test_alerts_prefixed(self):
        result = _flatten_section({"alerts": {"min_overall_score": 0.8, "notify_command": "echo hi"}})
        assert result == {"alert_min_overall_score": 0.8, "alert_notify_command": "echo hi"}

    def test_active_profiles_string_split(self):
        result = _flatten_section({"active_profiles": "ecc,budget"})
        assert result == {"active_profiles": ["ecc", "budget"]}

    def test_include_string_split(self):
        result = _flatten_section({"include": "ecc,mixed-storage"})
        assert result == {"include": ["ecc", "mixed-storage"]}


class TestLoadConfig:
    def test_explicit_nonexistent_raises(self):
        with pytest.raises(SystemExit, match="not found"):
            load_config("/nonexistent/path/should/not/exist.toml")

    def test_builtin_defaults(self):
        loaded = load_config(None)
        assert loaded.defaults["top"] == BUILTIN_DEFAULTS["top"]
        assert loaded.defaults["currency"] == "USD"
        assert "mixed-storage" in loaded.profiles
        assert "ecc" in loaded.profiles
        assert "cultscale" in loaded.profiles

    def test_config_file_overrides(self, tmp_config: Path):
        loaded = load_config(str(tmp_config))
        assert loaded.defaults["top"] == 3
        assert loaded.defaults["ecc_only"] is False
        assert loaded.defaults["inic_bonus"] == 0.20
        assert "test-budget" in loaded.profiles
        assert "Fake CPU 9000" in loaded.extra_cpu_specs

    def test_builtin_profiles_preserved(self, tmp_config: Path):
        loaded = load_config(str(tmp_config))
        assert "mixed-storage" in loaded.profiles
        assert "ecc" in loaded.profiles

    def test_extra_cpu_specs(self, tmp_config: Path):
        loaded = load_config(str(tmp_config))
        spec = loaded.extra_cpu_specs["Fake CPU 9000"]
        assert spec["cores"] == 128
        assert spec["threads"] == 256


class TestResolveSettings:
    def test_defaults_only(self):
        loaded = LoadedConfig(
            defaults={"top": 5, "ecc_only": True, "currency": "EUR"},
            profiles={},
            extra_cpu_specs={},
            source_path=None,
        )
        s, applied = resolve_settings(loaded, None, {})
        assert s["top"] == 5
        assert s["ecc_only"] is True
        assert s["currency"] == "EUR"
        assert s["url"].endswith("live_data_sb_EUR.json")
        assert applied == []

    def test_profile_overrides_defaults(self):
        loaded = LoadedConfig(
            defaults={"top": 5, "ecc_only": True, "min_ssd_drives": 0},
            profiles={"test": {"min_ssd_drives": 2, "description": "testing"}},
            extra_cpu_specs={},
            source_path=None,
        )
        s, applied = resolve_settings(loaded, "test", {})
        assert s["min_ssd_drives"] == 2
        assert s["top"] == 5
        assert applied == ["test"]

    def test_cli_overrides_profile(self):
        loaded = LoadedConfig(
            defaults={"top": 5, "ecc_only": True},
            profiles={"test": {"ecc_only": True, "description": "x"}},
            extra_cpu_specs={},
            source_path=None,
        )
        s, _ = resolve_settings(loaded, "test", {"ecc_only": False, "top": 20})
        assert s["ecc_only"] is False
        assert s["top"] == 20

    def test_unknown_profile_exits(self):
        loaded = LoadedConfig(defaults={}, profiles={}, extra_cpu_specs={}, source_path=None)
        with pytest.raises(SystemExit, match="Unknown profile"):
            resolve_settings(loaded, "nonexistent", {})

    def test_description_not_leaked(self):
        loaded = LoadedConfig(
            defaults={"top": 5},
            profiles={"x": {"description": "should not appear", "top": 10}},
            extra_cpu_specs={},
            source_path=None,
        )
        s, _ = resolve_settings(loaded, "x", {})
        assert "description" not in s
        assert s["top"] == 10

    def test_multiple_profiles_compose_left_to_right(self):
        loaded = LoadedConfig(
            defaults={"top": 5, "ecc_only": False, "min_ssd_drives": 0, "price_cap": None},
            profiles={
                "ecc": {"ecc_only": True, "description": "ECC"},
                "mixed-storage": {"min_ssd_drives": 2, "description": "Mixed"},
                "budget": {"price_cap": 60.0, "description": "Budget"},
            },
            extra_cpu_specs={},
            source_path=None,
        )
        s, applied = resolve_settings(loaded, ["ecc", "mixed-storage", "budget"], {})
        assert s["ecc_only"] is True
        assert s["min_ssd_drives"] == 2
        assert s["price_cap"] == 60.0
        assert applied == ["ecc", "mixed-storage", "budget"]

    def test_profile_includes_are_resolved(self):
        loaded = LoadedConfig(
            defaults={"ecc_only": False, "ssd_only": False, "min_ram_gb": 0},
            profiles={
                "ecc": {"ecc_only": True, "description": "ECC"},
                "ssd-only": {"ssd_only": True, "description": "SSD"},
                "high-memory": {"min_ram_gb": 64, "description": "RAM"},
                "ssd-compute": {
                    "include": ["ecc", "ssd-only", "high-memory"],
                    "description": "Combo",
                },
            },
            extra_cpu_specs={},
            source_path=None,
        )
        s, applied = resolve_settings(loaded, ["ssd-compute"], {})
        assert s["ecc_only"] is True
        assert s["ssd_only"] is True
        assert s["min_ram_gb"] == 64
        assert applied == ["ecc", "ssd-only", "high-memory", "ssd-compute"]

    def test_default_active_profiles_used_when_no_cli_profiles(self):
        loaded = LoadedConfig(
            defaults={"active_profiles": ["ecc"], "ecc_only": False},
            profiles={"ecc": {"ecc_only": True, "description": "ECC"}},
            extra_cpu_specs={},
            source_path=None,
        )
        s, applied = resolve_settings(loaded, None, {})
        assert s["ecc_only"] is True
        assert applied == ["ecc"]

    def test_include_cycle_exits(self):
        loaded = LoadedConfig(
            defaults={},
            profiles={
                "a": {"include": ["b"], "description": "A"},
                "b": {"include": ["a"], "description": "B"},
            },
            extra_cpu_specs={},
            source_path=None,
        )
        with pytest.raises(SystemExit, match="cycle"):
            resolve_settings(loaded, ["a"], {})
