"""Project factory configuration overlays the central roster."""

from __future__ import annotations

from pathlib import Path

import yaml

from adw_modules import agents


CENTRAL = """
defaults:
  model: central/model
  thinking: medium
  tools: [read, bash]
  data_dir: central-data
observability:
  db: central.db
  poll_ms: 500
quality:
  test:
    argv: [pytest]
agents:
  - name: builder
    purpose: central builder
    prompt_engineering:
      system: prompts/system.md
      user: prompts/user.md
"""


def _configs(tmp_path: Path, monkeypatch, project_text: str | None) -> tuple[Path, Path]:
    factory = tmp_path / "factory"
    factory.mkdir()
    central = factory / "sssf.config.yaml"
    central.write_text(CENTRAL)
    monkeypatch.setenv("FACTORY_ROOT", str(factory))
    project = tmp_path / "project" / ".factory" / "sssf.config.yaml"
    project.parent.mkdir(parents=True)
    if project_text is not None:
        project.write_text(project_text)
    return central, project


def test_nested_override_keeps_siblings(tmp_path: Path, monkeypatch, capsys) -> None:
    central, project = _configs(
        tmp_path, monkeypatch,
        "defaults:\n  model: project/model\nobservability:\n  poll_ms: 1000\n")

    cfg = agents.load_config(str(project))

    assert cfg.defaults.model == "project/model"
    assert cfg.defaults.thinking == "medium"
    assert cfg.observability.db == "central.db"
    assert cfg.observability.poll_ms == 1000
    assert [agent.name for agent in cfg.agents] == ["builder"]
    report = capsys.readouterr().err
    assert str(central) in report and str(project) in report


def test_project_can_opt_into_remote_pi_spawn(tmp_path: Path, monkeypatch) -> None:
    _, project = _configs(tmp_path, monkeypatch, "defaults:\n  pi_spawn: remote\n")

    cfg = agents.load_config(str(project))

    assert cfg.defaults.pi_spawn == "remote"


def test_list_replaces_instead_of_appending(tmp_path: Path, monkeypatch) -> None:
    _, project = _configs(tmp_path, monkeypatch, "defaults:\n  tools: [edit]\n")

    cfg = agents.load_config(str(project))

    assert cfg.defaults.tools == ["edit"]
    assert cfg.agents[0].tools == ["edit"]


def test_no_project_config_is_identical_to_central(tmp_path: Path, monkeypatch) -> None:
    central, _ = _configs(tmp_path, monkeypatch, None)

    cfg = agents.load_config(str(central))

    raw = yaml.safe_load(CENTRAL)
    assert cfg.defaults.model == raw["defaults"]["model"]
    assert cfg.defaults.tools == raw["defaults"]["tools"]
    assert cfg.observability.poll_ms == raw["observability"]["poll_ms"]
    assert [agent.name for agent in cfg.agents] == ["builder"]


def test_project_only_key_is_added(tmp_path: Path, monkeypatch) -> None:
    _, project = _configs(
        tmp_path, monkeypatch,
        "quality:\n  lint:\n    argv: [ruff, check]\n    operation: lint\n")

    cfg = agents.load_config(str(project))

    assert set(cfg.quality) == {"test", "lint"}
    assert cfg.quality["lint"].argv == ["ruff", "check"]


def test_runtime_paths_override_host_config(tmp_path: Path, monkeypatch) -> None:
    central, _ = _configs(tmp_path, monkeypatch, None)
    monkeypatch.setenv("FACTORY_DATA_DIR", "/runtime/data")
    monkeypatch.setenv("FACTORY_DB_PATH", "/runtime/factory.db")
    cfg = agents.load_config(str(central))
    assert cfg.defaults.data_dir == "/runtime/data"
    assert cfg.observability.db == "/runtime/factory.db"
