"""Unit tests for _atomic_write_json and path helpers in mcp_vm_blackbox._helpers."""

from __future__ import annotations

import json
from typing import TYPE_CHECKING

import pytest

from mcp_vm_blackbox._helpers import _atomic_write_json, default_blackbox_data_root, discover_repo_root_from_cwd

if TYPE_CHECKING:
    from pathlib import Path


@pytest.fixture(autouse=True)
def _clear_data_root_cache() -> None:
    """Clear the lru_cache on default_blackbox_data_root before each test.

    The cache is keyed on no arguments; env var and cwd changes made by
    monkeypatch would otherwise be invisible to subsequent calls within the
    same process.
    """
    default_blackbox_data_root.cache_clear()


# ---------------------------------------------------------------------------
# _atomic_write_json
# ---------------------------------------------------------------------------


def test_atomic_write_json_dict(tmp_path: Path) -> None:
    """Write a dict payload, read back, assert equality."""
    target = tmp_path / "out.json"
    payload = {"key": "value", "nested": {"a": 1}}
    _atomic_write_json(target, payload)
    assert json.loads(target.read_text()) == payload


def test_atomic_write_json_list(tmp_path: Path) -> None:
    """Write a list-of-dicts payload, read back, assert equality."""
    target = tmp_path / "out.json"
    payload = [{"id": 1, "name": "alpha"}, {"id": 2, "name": "beta"}]
    _atomic_write_json(target, payload)
    assert json.loads(target.read_text()) == payload


def test_atomic_write_json_overwrites(tmp_path: Path) -> None:
    """Writing twice to the same path keeps only the latest content."""
    target = tmp_path / "out.json"
    _atomic_write_json(target, {"version": 1})
    _atomic_write_json(target, {"version": 2})
    assert json.loads(target.read_text()) == {"version": 2}


def test_atomic_write_json_creates_parent_dirs(tmp_path: Path) -> None:
    """Writing to a nested non-existent path creates parent directories."""
    target = tmp_path / "deep" / "nested" / "dir" / "out.json"
    payload = {"created": True}
    _atomic_write_json(target, payload)
    assert json.loads(target.read_text()) == payload


# ---------------------------------------------------------------------------
# default_blackbox_data_root / discover_repo_root_from_cwd
# ---------------------------------------------------------------------------


def test_discover_repo_root_from_cwd_finds_git(monkeypatch: pytest.MonkeyPatch, tmp_path: Path) -> None:
    """Walking upward finds a directory containing ``.git``."""
    repo = tmp_path / "repo"
    repo.mkdir()
    (repo / ".git").mkdir()
    monkeypatch.chdir(repo)
    assert discover_repo_root_from_cwd() == repo.resolve()


def test_discover_repo_root_from_cwd_finds_blackbox_marker(monkeypatch: pytest.MonkeyPatch, tmp_path: Path) -> None:
    """A repo may only have ``.mcp-vm-blackbox`` (no ``.git``)."""
    repo = tmp_path / "bare"
    repo.mkdir()
    (repo / ".mcp-vm-blackbox").mkdir()
    monkeypatch.chdir(repo)
    assert discover_repo_root_from_cwd() == repo.resolve()


def test_default_blackbox_data_root_respects_env(monkeypatch: pytest.MonkeyPatch, tmp_path: Path) -> None:
    """MCP_VM_BLACKBOX_DATA_ROOT wins over cwd discovery."""
    target = tmp_path / "custom-data"
    target.mkdir()
    monkeypatch.setenv("MCP_VM_BLACKBOX_DATA_ROOT", str(target))
    assert default_blackbox_data_root() == target.resolve()


def test_default_blackbox_data_root_uses_repo_when_under_git(monkeypatch: pytest.MonkeyPatch, tmp_path: Path) -> None:
    """Under a git repo, data root is ``<repo>/.mcp-vm-blackbox``."""
    repo = tmp_path / "proj"
    repo.mkdir()
    (repo / ".git").mkdir()
    sub = repo / "packages" / "foo"
    sub.mkdir(parents=True)
    monkeypatch.chdir(sub)
    monkeypatch.delenv("MCP_VM_BLACKBOX_DATA_ROOT", raising=False)
    assert default_blackbox_data_root() == (repo / ".mcp-vm-blackbox").resolve()


def test_default_blackbox_data_root_fallback_home(monkeypatch: pytest.MonkeyPatch, tmp_path: Path) -> None:
    """With no markers and no env, use ``~/.mcp-vm-blackbox``."""
    monkeypatch.chdir(tmp_path)
    fake_home = tmp_path / "h"
    fake_home.mkdir()
    monkeypatch.setenv("HOME", str(fake_home))
    monkeypatch.delenv("MCP_VM_BLACKBOX_DATA_ROOT", raising=False)
    assert default_blackbox_data_root() == (fake_home / ".mcp-vm-blackbox").resolve()
