"""Tests for spens.templates."""

import json
from pathlib import Path

import pytest
from spens.templates import (
    TemplateNotFoundError,
    list_agents,
    list_environments,
    load_agent,
    load_environment,
)


def _write_template(workspace: Path, name: str, template_type: str, **fields) -> None:
    templates_dir = workspace / "templates"
    templates_dir.mkdir(exist_ok=True)
    data = {"template_type": template_type, "name": name, **fields}
    (templates_dir / f"{name}.json").write_text(json.dumps(data), encoding="utf-8")


def test_loads_builtin_environment() -> None:
    env = load_environment("node-20")
    assert env["name"] == "node-20"
    assert env["base-image"] == "node:20.18.0-bookworm"
    assert env["template_type"] == "environment"


def test_loads_builtin_agent() -> None:
    agent = load_agent("opencode")
    assert agent["name"] == "opencode"
    assert "installation_command" in agent


def test_missing_environment_raises() -> None:
    with pytest.raises(TemplateNotFoundError):
        load_environment("does-not-exist")


def test_missing_agent_raises() -> None:
    with pytest.raises(TemplateNotFoundError):
        load_agent("does-not-exist")


def test_local_environment_overrides_builtin(tmp_path) -> None:
    _write_template(tmp_path, "node-20", "environment", **{"base-image": "node:99-custom"})
    env = load_environment("node-20", tmp_path)
    assert env["base-image"] == "node:99-custom"


def test_local_agent_overrides_builtin(tmp_path) -> None:
    _write_template(tmp_path, "opencode", "agent", **{"installation_command": "echo custom"})
    agent = load_agent("opencode", tmp_path)
    assert agent["installation_command"] == "echo custom"


def test_local_template_with_wrong_type_ignored(tmp_path) -> None:
    _write_template(tmp_path, "node-20", "agent", **{"base-image": "node:99-custom"})
    env = load_environment("node-20", tmp_path)
    assert env["base-image"] == "node:20.18.0-bookworm"


def test_environment_from_json_file_path(tmp_path) -> None:
    env_file = tmp_path / "my-env.json"
    env_file.write_text(
        json.dumps({"template_type": "environment", "name": "my-env", "base-image": "node:99-custom"}),
        encoding="utf-8",
    )
    env = load_environment("my-env.json", tmp_path)
    assert env["name"] == "my-env"
    assert env["base-image"] == "node:99-custom"


def test_agent_from_json_file_path(tmp_path) -> None:
    agent_file = tmp_path / "my-agent.json"
    agent_file.write_text(
        json.dumps({"template_type": "agent", "name": "my-agent", "installation_command": "echo hi"}),
        encoding="utf-8",
    )
    agent = load_agent("my-agent.json", tmp_path)
    assert agent["name"] == "my-agent"
    assert agent["installation_command"] == "echo hi"


def test_json_file_path_takes_precedence_over_builtin(tmp_path) -> None:
    env_file = tmp_path / "node-20.json"
    env_file.write_text(
        json.dumps({"template_type": "environment", "name": "node-20", "base-image": "node:99-custom"}),
        encoding="utf-8",
    )
    env = load_environment("node-20.json", tmp_path)
    assert env["base-image"] == "node:99-custom"


def test_absolute_json_file_path(tmp_path) -> None:
    env_file = tmp_path / "abs-env.json"
    env_file.write_text(
        json.dumps({"name": "abs-env", "base-image": "node:1"}), encoding="utf-8"
    )
    env = load_environment(str(env_file), tmp_path)
    assert env["name"] == "abs-env"


def test_missing_json_file_path_raises(tmp_path) -> None:
    with pytest.raises(TemplateNotFoundError):
        load_environment("missing-env.json", tmp_path)
    with pytest.raises(TemplateNotFoundError):
        load_agent("missing-agent.json", tmp_path)


def test_list_includes_builtin_templates() -> None:
    env_names = [name for name, _ in list_environments()]
    agent_names = list_agents()
    assert "node-20" in env_names
    assert "python-3.12" in env_names
    assert "opencode" in agent_names
    assert "codex" in agent_names


def test_list_includes_local_templates(tmp_path) -> None:
    _write_template(tmp_path, "custom-env", "environment", **{"base-image": "node:1"})
    _write_template(tmp_path, "custom-agent", "agent")
    env_names = [name for name, _ in list_environments(tmp_path)]
    agent_names = list_agents(tmp_path)
    assert "custom-env" in env_names
    assert "custom-agent" in agent_names


def test_list_is_sorted(tmp_path) -> None:
    env_names = [name for name, _ in list_environments(tmp_path)]
    agent_names = list_agents(tmp_path)
    assert env_names == sorted(env_names)
    assert agent_names == sorted(agent_names)
