import json
from pathlib import Path

import pytest

from ki2_externai.config import load_config


def _write_config(path: Path, data: dict) -> None:
    """Persist a small JSON payload to the requested location."""
    path.parent.mkdir(parents=True, exist_ok=True)
    path.write_text(json.dumps(data), encoding="utf-8")


def test_load_config_from_root(tmp_path, monkeypatch):
    """The loader should accept `externai.json` sitting at the project root."""
    config_path = tmp_path / "externai.json"
    _write_config(
        config_path,
        {
            "version": 1,
            "externalsDir": "./.externals",
            "imports": [{"name": "libA", "path": "src/libA"}],
        },
    )
    monkeypatch.chdir(tmp_path)

    config = load_config()

    assert config.externals_dir == (tmp_path / ".externals").resolve()
    assert len(config.imports) == 1
    assert config.imports[0].name == "libA"
    assert config.imports[0].path is not None


def test_load_config_from_dot_externals(tmp_path, monkeypatch):
    """The loader should fallback to `.externals/externai.json` when the root file is absent."""
    dot_dir = tmp_path / ".externals"
    config_path = dot_dir / "externai.json"
    _write_config(
        config_path,
        {
            "version": 1,
            "imports": ["libA"],
        },
    )
    monkeypatch.chdir(tmp_path)

    config = load_config()

    assert config.externals_dir == (tmp_path / ".externals").resolve()
    assert config.imports[0].name == "libA"
    assert config.imports[0].path is None


def test_missing_config_raises(tmp_path, monkeypatch):
    """Missing configuration should raise with a friendly message."""
    monkeypatch.chdir(tmp_path)
    with pytest.raises(SystemExit) as excinfo:
        load_config()
    assert "Config not found" in str(excinfo.value)


def test_invalid_version_rejected(tmp_path, monkeypatch):
    """A config that advertises the wrong schema version should error."""
    config_path = tmp_path / "externai.json"
    _write_config(
        config_path,
        {
            "version": 2,
            "imports": ["libA"],
        },
    )
    monkeypatch.chdir(tmp_path)

    with pytest.raises(SystemExit) as excinfo:
        load_config()
    assert "Unsupported config version" in str(excinfo.value)


def test_non_array_imports(tmp_path, monkeypatch):
    """The `imports` value must be an array."""
    config_path = tmp_path / "externai.json"
    _write_config(config_path, {"imports": {"name": "libA"}})
    monkeypatch.chdir(tmp_path)

    with pytest.raises(SystemExit) as excinfo:
        load_config()
    assert "`imports` must be an array" in str(excinfo.value)


def test_empty_imports_list_is_valid(tmp_path, monkeypatch):
    """An empty imports list should be accepted and mean 'nothing to mount'."""
    config_path = tmp_path / "externai.json"
    _write_config(config_path, {"version": 1, "imports": []})
    monkeypatch.chdir(tmp_path)

    config = load_config()

    assert config.imports == []


def test_empty_mount_string_rejected(tmp_path, monkeypatch):
    """A provided mount key must be non-empty."""
    config_path = tmp_path / "externai.json"
    _write_config(
        config_path,
        {"version": 1, "imports": [{"name": "libA", "mount": ""}]},
    )
    monkeypatch.chdir(tmp_path)

    with pytest.raises(SystemExit) as excinfo:
        load_config()
    assert "`mount` must be a non-empty string when provided" in str(excinfo.value)
