"""Tests for the matrix configuration loader utility."""

from pathlib import Path

import pytest
import yaml

from infrastructure.matrix_config import (
    AgentConfig,
    AgentsConfig,
    EnvironmentConfig,
    FeaturesConfig,
    LightingConfig,
    MatrixConfig,
    PointLight,
    load_from_yaml,
)


class TestPointLight:
    """Tests for PointLight dataclass."""

    def test_default_values(self):
        """PointLight has correct defaults."""
        pl = PointLight()
        assert pl.color == "#FFFFFF"
        assert pl.intensity == 1.0
        assert pl.position == {"x": 0, "y": 0, "z": 0}

    def test_from_dict_full(self):
        """PointLight.from_dict loads all fields."""
        data = {
            "color": "#FF0000",
            "intensity": 2.5,
            "position": {"x": 1, "y": 2, "z": 3},
        }
        pl = PointLight.from_dict(data)
        assert pl.color == "#FF0000"
        assert pl.intensity == 2.5
        assert pl.position == {"x": 1, "y": 2, "z": 3}

    def test_from_dict_partial(self):
        """PointLight.from_dict fills missing fields with defaults."""
        data = {"color": "#00FF00"}
        pl = PointLight.from_dict(data)
        assert pl.color == "#00FF00"
        assert pl.intensity == 1.0
        assert pl.position == {"x": 0, "y": 0, "z": 0}


class TestLightingConfig:
    """Tests for LightingConfig dataclass."""

    def test_default_values(self):
        """LightingConfig has correct Workshop+Matrix blend defaults."""
        cfg = LightingConfig()
        assert cfg.ambient_color == "#FFAA55"  # Warm amber (Workshop)
        assert cfg.ambient_intensity == 0.5
        assert len(cfg.point_lights) == 3
        # First light is warm amber center
        assert cfg.point_lights[0].color == "#FFAA55"
        # Second light is cool blue (Matrix)
        assert cfg.point_lights[1].color == "#3B82F6"

    def test_from_dict_full(self):
        """LightingConfig.from_dict loads all fields."""
        data = {
            "ambient_color": "#123456",
            "ambient_intensity": 0.8,
            "point_lights": [
                {"color": "#ABCDEF", "intensity": 1.5, "position": {"x": 1, "y": 1, "z": 1}}
            ],
        }
        cfg = LightingConfig.from_dict(data)
        assert cfg.ambient_color == "#123456"
        assert cfg.ambient_intensity == 0.8
        assert len(cfg.point_lights) == 1
        assert cfg.point_lights[0].color == "#ABCDEF"

    def test_from_dict_empty_list_uses_defaults(self):
        """Empty point_lights list triggers default lights."""
        data = {"ambient_color": "#000000", "point_lights": []}
        cfg = LightingConfig.from_dict(data)
        assert cfg.ambient_color == "#000000"
        assert len(cfg.point_lights) == 3  # Default lights

    def test_from_dict_none(self):
        """LightingConfig.from_dict handles None."""
        cfg = LightingConfig.from_dict(None)
        assert cfg.ambient_color == "#FFAA55"
        assert len(cfg.point_lights) == 3


class TestEnvironmentConfig:
    """Tests for EnvironmentConfig dataclass."""

    def test_default_values(self):
        """EnvironmentConfig has correct defaults."""
        cfg = EnvironmentConfig()
        assert cfg.rain_enabled is False
        assert cfg.starfield_enabled is True  # Matrix starfield
        assert cfg.fog_color == "#0f0f23"
        assert cfg.fog_density == 0.02

    def test_from_dict_full(self):
        """EnvironmentConfig.from_dict loads all fields."""
        data = {
            "rain_enabled": True,
            "starfield_enabled": False,
            "fog_color": "#FFFFFF",
            "fog_density": 0.1,
        }
        cfg = EnvironmentConfig.from_dict(data)
        assert cfg.rain_enabled is True
        assert cfg.starfield_enabled is False
        assert cfg.fog_color == "#FFFFFF"
        assert cfg.fog_density == 0.1

    def test_from_dict_partial(self):
        """EnvironmentConfig.from_dict fills missing fields."""
        data = {"rain_enabled": True}
        cfg = EnvironmentConfig.from_dict(data)
        assert cfg.rain_enabled is True
        assert cfg.starfield_enabled is True  # Default
        assert cfg.fog_color == "#0f0f23"


class TestFeaturesConfig:
    """Tests for FeaturesConfig dataclass."""

    def test_default_values_all_enabled(self):
        """FeaturesConfig defaults to all features enabled."""
        cfg = FeaturesConfig()
        assert cfg.chat_enabled is True
        assert cfg.visitor_avatars is True
        assert cfg.pip_familiar is True
        assert cfg.workshop_portal is True

    def test_from_dict_full(self):
        """FeaturesConfig.from_dict loads all fields."""
        data = {
            "chat_enabled": False,
            "visitor_avatars": False,
            "pip_familiar": False,
            "workshop_portal": False,
        }
        cfg = FeaturesConfig.from_dict(data)
        assert cfg.chat_enabled is False
        assert cfg.visitor_avatars is False
        assert cfg.pip_familiar is False
        assert cfg.workshop_portal is False

    def test_from_dict_partial(self):
        """FeaturesConfig.from_dict fills missing fields."""
        data = {"chat_enabled": False}
        cfg = FeaturesConfig.from_dict(data)
        assert cfg.chat_enabled is False
        assert cfg.visitor_avatars is True  # Default
        assert cfg.pip_familiar is True
        assert cfg.workshop_portal is True


class TestAgentConfig:
    """Tests for AgentConfig dataclass."""

    def test_default_values(self):
        """AgentConfig has correct defaults."""
        cfg = AgentConfig()
        assert cfg.name == ""
        assert cfg.role == ""
        assert cfg.enabled is True

    def test_from_dict_full(self):
        """AgentConfig.from_dict loads all fields."""
        data = {"name": "Timmy", "role": "guide", "enabled": False}
        cfg = AgentConfig.from_dict(data)
        assert cfg.name == "Timmy"
        assert cfg.role == "guide"
        assert cfg.enabled is False


class TestAgentsConfig:
    """Tests for AgentsConfig dataclass."""

    def test_default_values(self):
        """AgentsConfig has correct defaults."""
        cfg = AgentsConfig()
        assert cfg.default_count == 5
        assert cfg.max_count == 20
        assert cfg.agents == []

    def test_from_dict_with_agents(self):
        """AgentsConfig.from_dict loads agent list."""
        data = {
            "default_count": 10,
            "max_count": 50,
            "agents": [
                {"name": "Timmy", "role": "guide", "enabled": True},
                {"name": "Helper", "role": "assistant"},
            ],
        }
        cfg = AgentsConfig.from_dict(data)
        assert cfg.default_count == 10
        assert cfg.max_count == 50
        assert len(cfg.agents) == 2
        assert cfg.agents[0].name == "Timmy"
        assert cfg.agents[1].enabled is True  # Default


class TestMatrixConfig:
    """Tests for MatrixConfig dataclass."""

    def test_default_values(self):
        """MatrixConfig has correct composite defaults."""
        cfg = MatrixConfig()
        assert isinstance(cfg.lighting, LightingConfig)
        assert isinstance(cfg.environment, EnvironmentConfig)
        assert isinstance(cfg.features, FeaturesConfig)
        assert isinstance(cfg.agents, AgentsConfig)
        # Check the blend
        assert cfg.lighting.ambient_color == "#FFAA55"
        assert cfg.environment.starfield_enabled is True
        assert cfg.features.chat_enabled is True

    def test_from_dict_full(self):
        """MatrixConfig.from_dict loads all sections."""
        data = {
            "lighting": {"ambient_color": "#000000"},
            "environment": {"rain_enabled": True},
            "features": {"chat_enabled": False},
            "agents": {"default_count": 3},
        }
        cfg = MatrixConfig.from_dict(data)
        assert cfg.lighting.ambient_color == "#000000"
        assert cfg.environment.rain_enabled is True
        assert cfg.features.chat_enabled is False
        assert cfg.agents.default_count == 3

    def test_from_dict_partial(self):
        """MatrixConfig.from_dict fills missing sections with defaults."""
        data = {"lighting": {"ambient_color": "#111111"}}
        cfg = MatrixConfig.from_dict(data)
        assert cfg.lighting.ambient_color == "#111111"
        assert cfg.environment.starfield_enabled is True  # Default
        assert cfg.features.pip_familiar is True  # Default

    def test_from_dict_none(self):
        """MatrixConfig.from_dict handles None."""
        cfg = MatrixConfig.from_dict(None)
        assert cfg.lighting.ambient_color == "#FFAA55"
        assert cfg.features.chat_enabled is True

    def test_to_dict_roundtrip(self):
        """MatrixConfig.to_dict produces serializable output."""
        cfg = MatrixConfig()
        data = cfg.to_dict()
        assert isinstance(data, dict)
        assert "lighting" in data
        assert "environment" in data
        assert "features" in data
        assert "agents" in data
        # Verify point lights are included
        assert len(data["lighting"]["point_lights"]) == 3


class TestLoadFromYaml:
    """Tests for load_from_yaml function."""

    def test_loads_valid_yaml(self, tmp_path: Path):
        """load_from_yaml reads a valid YAML file."""
        config_path = tmp_path / "matrix.yaml"
        data = {
            "lighting": {"ambient_color": "#TEST11"},
            "features": {"chat_enabled": False},
        }
        config_path.write_text(yaml.safe_dump(data))

        cfg = load_from_yaml(config_path)
        assert cfg.lighting.ambient_color == "#TEST11"
        assert cfg.features.chat_enabled is False

    def test_missing_file_returns_defaults(self, tmp_path: Path):
        """load_from_yaml returns defaults when file doesn't exist."""
        config_path = tmp_path / "nonexistent.yaml"
        cfg = load_from_yaml(config_path)
        assert cfg.lighting.ambient_color == "#FFAA55"
        assert cfg.features.chat_enabled is True

    def test_empty_file_returns_defaults(self, tmp_path: Path):
        """load_from_yaml returns defaults for empty file."""
        config_path = tmp_path / "empty.yaml"
        config_path.write_text("")
        cfg = load_from_yaml(config_path)
        assert cfg.lighting.ambient_color == "#FFAA55"

    def test_invalid_yaml_returns_defaults(self, tmp_path: Path):
        """load_from_yaml returns defaults for invalid YAML."""
        config_path = tmp_path / "invalid.yaml"
        config_path.write_text("not: valid: yaml: [")
        cfg = load_from_yaml(config_path)
        assert cfg.lighting.ambient_color == "#FFAA55"
        assert cfg.features.chat_enabled is True

    def test_non_dict_yaml_returns_defaults(self, tmp_path: Path):
        """load_from_yaml returns defaults when YAML is not a dict."""
        config_path = tmp_path / "list.yaml"
        config_path.write_text("- item1\n- item2")
        cfg = load_from_yaml(config_path)
        assert cfg.lighting.ambient_color == "#FFAA55"

    def test_loads_actual_config_file(self):
        """load_from_yaml can load the project's config/matrix.yaml."""
        repo_root = Path(__file__).parent.parent.parent
        config_path = repo_root / "config" / "matrix.yaml"
        if not config_path.exists():
            pytest.skip("config/matrix.yaml not found")

        cfg = load_from_yaml(config_path)
        # Verify it loaded with expected values
        assert cfg.lighting.ambient_color == "#FFAA55"
        assert len(cfg.lighting.point_lights) == 3
        assert cfg.environment.starfield_enabled is True
        assert cfg.features.workshop_portal is True

    def test_str_path_accepted(self, tmp_path: Path):
        """load_from_yaml accepts string path."""
        config_path = tmp_path / "matrix.yaml"
        config_path.write_text(yaml.safe_dump({"lighting": {"ambient_intensity": 0.9}}))

        cfg = load_from_yaml(str(config_path))
        assert cfg.lighting.ambient_intensity == 0.9
