"""Tests for the cross-profile soft guard wired into write_file / patch /
skill_manage.

The classifier is tested in tests/agent/test_file_safety_cross_profile.py.
This file tests that the tool surfaces:

  1. Refuse cross-profile writes by default and return the warning.
  2. Accept cross-profile writes when cross_profile=True is passed.
  3. Continue to accept in-profile writes normally.
  4. skill_manage's "not found" error names other profiles where the
     skill exists.
"""
from __future__ import annotations

import json
from pathlib import Path

import pytest

@pytest.fixture
def fake_hermes(tmp_path, monkeypatch):
    """Build a two-profile Hermes layout and point HERMES_HOME at
    the hermes-security profile (matching the original-incident shape).
    """
    root = tmp_path / "fake-hermes"
    (root / "skills" / "shared-skill").mkdir(parents=True)
    (root / "skills" / "shared-skill" / "SKILL.md").write_text(
        "---\nname: shared-skill\ndescription: default copy.\n---\n"
    )

    sec_home = root / "profiles" / "hermes-security"
    (sec_home / "skills").mkdir(parents=True)

    coder_home = root / "profiles" / "coder"
    (coder_home / "skills").mkdir(parents=True)

    monkeypatch.setenv("HERMES_HOME", str(sec_home))

    import hermes_constants
    monkeypatch.setattr(hermes_constants, "get_default_hermes_root", lambda: root)

    import agent.file_safety as fs
    monkeypatch.setattr(fs, "_hermes_home_path", lambda: sec_home)
    monkeypatch.setattr(fs, "_hermes_root_path", lambda: root)

    return {
        "root": root,
        "sec_home": sec_home,
        "coder_home": coder_home,
    }

# ---------------------------------------------------------------------------
# write_file
# ---------------------------------------------------------------------------

class TestWriteFileCrossProfileGuard:

    def test_cross_profile_write_allowed_guard_retired(self, fake_hermes):
        """Guard RETIRED (maintainer decision): profiles are not isolated —
        the same OS user owns every profile dir and the terminal tool
        always could write them. Cross-profile writes now succeed; the
        system prompt's profile hint is the only steering."""
        from tools.file_tools import read_file_tool, write_file_tool
        target = fake_hermes["root"] / "skills" / "shared-skill" / "SKILL.md"
        assert not json.loads(read_file_tool(str(target))).get("error")
        result_json = write_file_tool(str(target), "cross-profile write, allowed")
        result = json.loads(result_json)
        assert not result.get("error"), f"guard retired; write must succeed: {result}"
        assert target.read_text() == "cross-profile write, allowed"

# ---------------------------------------------------------------------------
# patch
# ---------------------------------------------------------------------------

class TestPatchCrossProfileGuard:

    def test_cross_profile_patch_bypass(self, fake_hermes):
        from tools.file_tools import patch_tool
        target = fake_hermes["root"] / "skills" / "shared-skill" / "SKILL.md"
        result_json = patch_tool(
            mode="replace",
            path=str(target),
            old_string="default copy.",
            new_string="user-directed update.",
            cross_profile=True,
        )
        result = json.loads(result_json)
        assert not result.get("error"), f"cross_profile still handler-accepted (compat): {result}"
        assert "user-directed update." in target.read_text()

    def test_v4a_patch_writes_through_guard_retired(self, fake_hermes):
        """V4A patch to a cross-profile path succeeds (guard retired).
        V4A patches embed target paths in the patch body; path extraction
        for the surviving mirror guards still runs, but cross-profile
        targets are no longer refused."""
        from tools.file_tools import patch_tool
        target = fake_hermes["root"] / "skills" / "shared-skill" / "SKILL.md"
        v4a = (
            "*** Begin Patch\n"
            f"*** Update File: {target}\n"
            "@@\n"
            "-default copy.\n"
            "+v4a cross-profile write, allowed.\n"
            "*** End Patch"
        )
        result_json = patch_tool(mode="patch", patch=v4a)
        result = json.loads(result_json)
        assert not result.get("error"), f"guard retired; V4A must succeed: {result}"
        assert "v4a cross-profile write, allowed." in target.read_text()

# ---------------------------------------------------------------------------
# skill_manage — error message naming other profile (item D)
# ---------------------------------------------------------------------------

class TestSkillManageCrossProfileErrorUX:
    def _make_skill_in_profile(self, profile_dir: Path, name: str):
        d = profile_dir / "skills" / name
        d.mkdir(parents=True, exist_ok=True)
        (d / "SKILL.md").write_text(
            f"---\nname: {name}\ndescription: a skill.\n---\n"
        )

    def test_error_names_other_profile_when_skill_lives_there(
        self, fake_hermes, monkeypatch
    ):
        """The original incident shape — model expects 'foo' in active
        profile, but 'foo' lives in default. Error must point at default."""
        self._make_skill_in_profile(fake_hermes["root"], "default-only-skill")

        # Re-import the module so SKILLS_DIR picks up HERMES_HOME (set in
        # the fixture). Skill_manager_tool computes SKILLS_DIR at import.
        import importlib
        import tools.skill_manager_tool
        importlib.reload(tools.skill_manager_tool)
        from tools.skill_manager_tool import _skill_not_found_error

        err = _skill_not_found_error("default-only-skill")
        assert "not found in active profile 'hermes-security'" in err
        assert "default" in err

    def test_genuinely_missing_skill_keeps_helpful_hint(
        self, fake_hermes, monkeypatch
    ):
        """When no profile has the skill, error falls back to skills_list hint."""
        import importlib
        import tools.skill_manager_tool
        importlib.reload(tools.skill_manager_tool)
        from tools.skill_manager_tool import _skill_not_found_error

        err = _skill_not_found_error("totally-imaginary-skill")
        assert "not found in active profile 'hermes-security'" in err
        assert "skills_list" in err

# ---------------------------------------------------------------------------
# System prompt active-profile line (item B)
# ---------------------------------------------------------------------------
