"""Tests for policy enforcement: dry-run must block apply actions."""

from milco.policy.policy import (
    check_no_apply_no_write,
    check_diff_only,
    check_evidence_first,
    check_one_tool_per_step,
    run_policy_gate,
)


def test_no_apply_blocks_apply_patch():
    ok, msg = check_no_apply_no_write(apply_mode=False, action="apply_patch")
    assert not ok
    assert "blocked" in msg.lower()


def test_no_apply_blocks_exec_command():
    ok, msg = check_no_apply_no_write(apply_mode=False, action="exec_command")
    assert not ok


def test_apply_mode_allows_apply_patch():
    ok, msg = check_no_apply_no_write(apply_mode=True, action="apply_patch")
    assert ok


def test_safe_action_always_allowed():
    ok, _ = check_no_apply_no_write(apply_mode=False, action="read_file")
    assert ok


def test_diff_only_valid():
    diff = "--- a/map.json\n+++ b/map.json\n@@ -0,0 +1 @@\n+content\n"
    ok, _ = check_diff_only(diff)
    assert ok


def test_diff_only_invalid():
    ok, msg = check_diff_only("just some random text")
    assert not ok
    assert "unified diff" in msg.lower()


def test_diff_only_empty():
    ok, _ = check_diff_only("")
    assert ok


def test_evidence_first_pass():
    ok, _ = check_evidence_first("# Evidence\n\nFiles found.")
    assert ok


def test_evidence_first_fail_empty():
    ok, _ = check_evidence_first("")
    assert not ok


def test_evidence_first_fail_none():
    ok, _ = check_evidence_first(None)
    assert not ok


VALID_PLAN = """\
# Summary

## Plan

### Step 1: Scan

- tool: fs_tools.scan_repo

### Step 2: Generate diff

- tool: fixer.generate_map_diff
"""


def test_one_tool_per_step_valid():
    ok, _ = check_one_tool_per_step(VALID_PLAN)
    assert ok


def test_one_tool_per_step_two_tools():
    bad = """\
### Step 1: Do stuff

- tool: a
- tool: b
"""
    ok, msg = check_one_tool_per_step(bad)
    assert not ok
    assert "2 tool entries" in msg


def test_run_policy_gate_dry_run():
    diff = "--- a/x\n+++ b/x\n@@ -1 +1 @@\n-old\n+new\n"
    result = run_policy_gate(
        apply_mode=False,
        diff_text=diff,
        evidence_text="Some evidence",
        summary_text=VALID_PLAN,
    )
    assert result["diff_only"]["pass"]
    assert result["evidence_first"]["pass"]
    assert result["one_tool_per_step"]["pass"]
    # In dry-run, the guard passes (blocking apply is correct behavior)
    assert result["no_apply_guard"]["pass"]
    assert result["no_apply_guard"]["enforced"]  # but apply IS blocked
