"""Tests for configuration loading."""

import os
import pytest
import yaml

from opencypher_compliance.config import load_config, load_multi_config, ENV_PREFIX


@pytest.fixture
def config_file(tmp_path):
    """Create a temporary config file with the databases list format."""
    data = {
        "databases": [
            {
                "name": "Test DB",
                "adapter": "bolt",
                "host": "localhost",
                "port": 7687,
                "auth": {"username": "neo4j", "password": "test"},
            }
        ]
    }
    path = tmp_path / "config.yaml"
    path.write_text(yaml.dump(data))
    return path


class TestLoadConfig:
    """Tests for load_config (inline flags / env vars path)."""

    def test_missing_adapter_raises(self, tmp_path):
        path = tmp_path / "empty.yaml"
        path.write_text("database:\n  host: localhost\n")
        with pytest.raises(ValueError, match="No adapter"):
            load_config(path)

    def test_no_config_file_with_env(self, monkeypatch):
        monkeypatch.setenv(f"{ENV_PREFIX}ADAPTER", "falkordb")
        monkeypatch.setenv(f"{ENV_PREFIX}HOST", "myhost")
        monkeypatch.setenv(f"{ENV_PREFIX}PORT", "6379")
        config = load_config()
        assert config["database"]["adapter"] == "falkordb"
        assert config["database"]["host"] == "myhost"
        assert config["database"]["port"] == 6379

    def test_env_overrides_yaml(self, tmp_path, monkeypatch):
        data = {"database": {"adapter": "bolt", "host": "localhost", "port": 7687}}
        path = tmp_path / "config.yaml"
        path.write_text(yaml.dump(data))
        monkeypatch.setenv(f"{ENV_PREFIX}HOST", "override-host")
        config = load_config(path)
        assert config["database"]["host"] == "override-host"
        assert config["database"]["adapter"] == "bolt"

    def test_cli_overrides_env_and_yaml(self, tmp_path, monkeypatch):
        data = {"database": {"adapter": "bolt", "host": "localhost", "port": 7687}}
        path = tmp_path / "config.yaml"
        path.write_text(yaml.dump(data))
        monkeypatch.setenv(f"{ENV_PREFIX}HOST", "env-host")
        config = load_config(path, cli_overrides={"host": "cli-host"})
        assert config["database"]["host"] == "cli-host"

    def test_cli_none_values_ignored(self, tmp_path):
        data = {"database": {"adapter": "bolt", "host": "localhost", "port": 7687}}
        path = tmp_path / "config.yaml"
        path.write_text(yaml.dump(data))
        config = load_config(path, cli_overrides={"host": None})
        assert config["database"]["host"] == "localhost"

    def test_nonexistent_config_path_raises(self):
        with pytest.raises(FileNotFoundError, match="Config file not found"):
            load_config("/nonexistent/config.yaml")

    def test_env_username_password(self, monkeypatch):
        monkeypatch.setenv(f"{ENV_PREFIX}ADAPTER", "bolt")
        monkeypatch.setenv(f"{ENV_PREFIX}USERNAME", "user1")
        monkeypatch.setenv(f"{ENV_PREFIX}PASSWORD", "pass1")
        config = load_config()
        assert config["database"]["auth"]["username"] == "user1"
        assert config["database"]["auth"]["password"] == "pass1"


class TestLoadMultiConfig:
    def test_databases_list(self, tmp_path):
        data = {
            "databases": [
                {"name": "Neo4j", "adapter": "bolt", "host": "localhost", "port": 7687,
                 "auth": {"username": "neo4j", "password": "test"}},
                {"name": "FalkorDB", "adapter": "falkordb", "host": "localhost", "port": 6379},
            ]
        }
        path = tmp_path / "multi.yaml"
        path.write_text(yaml.dump(data))
        configs = load_multi_config(path)
        assert len(configs) == 2
        assert configs[0]["database"]["name"] == "Neo4j"
        assert configs[0]["database"]["adapter"] == "bolt"
        assert configs[1]["database"]["name"] == "FalkorDB"

    def test_single_entry_list(self, config_file):
        configs = load_multi_config(config_file)
        assert len(configs) == 1
        assert configs[0]["database"]["adapter"] == "bolt"

    def test_defaults_name_to_adapter(self, tmp_path):
        data = {"databases": [{"adapter": "bolt", "host": "localhost", "port": 7687}]}
        path = tmp_path / "noname.yaml"
        path.write_text(yaml.dump(data))
        configs = load_multi_config(path)
        assert configs[0]["database"]["name"] == "bolt"

    def test_missing_adapter_raises(self, tmp_path):
        data = {"databases": [{"name": "Bad", "host": "localhost"}]}
        path = tmp_path / "bad.yaml"
        path.write_text(yaml.dump(data))
        with pytest.raises(ValueError, match="missing 'adapter'"):
            load_multi_config(path)

    def test_empty_list_raises(self, tmp_path):
        data = {"databases": []}
        path = tmp_path / "empty.yaml"
        path.write_text(yaml.dump(data))
        with pytest.raises(ValueError, match="empty"):
            load_multi_config(path)

    def test_nonexistent_file_raises(self):
        with pytest.raises(FileNotFoundError):
            load_multi_config("/nonexistent/config.yaml")

    def test_old_database_key_rejected(self, tmp_path):
        data = {"database": {"adapter": "bolt", "host": "localhost"}}
        path = tmp_path / "old.yaml"
        path.write_text(yaml.dump(data))
        with pytest.raises(ValueError, match="'databases' list"):
            load_multi_config(path)
