"""Tests for fixer producing valid unified diffs."""

import re
from milco.core.run_context import RunContext
from milco.core.artifacts import write_artifact
from milco.fix.fixer import run_fix


def _make_ctx(tmp_path, apply=False, confirm=False):
    contract = tmp_path / "TASK_CONTRACT.md"
    contract_text = (
        "# Task Contract\n\n"
        "## Goal\n\nGenerate map.json.\n\n"
        "## Scope\n\nRepo scan.\n\n"
        "## Out of scope\n\nNothing.\n\n"
        "## Success Criteria\n\nmap.json created.\n\n"
        "## Constraints\n\nNone.\n\n"
        "## Approvals required\n\n"
    )
    if confirm:
        contract_text += "CONFIRM APPLY\n\n"
    else:
        contract_text += "None.\n\n"
    contract_text += "## Notes\n\nNone.\n"
    contract.write_text(contract_text, encoding="utf-8")

    ctx = RunContext(
        repo_root=tmp_path,
        run_id="test-fix",
        apply_mode=apply,
        contract_path=str(contract),
    )
    # Fixer needs evidence.md to exist
    write_artifact(ctx, "evidence.md", "# Evidence\n\nSome evidence here.\n")
    return ctx


def test_fix_produces_diff_dry_run(tmp_path):
    ctx = _make_ctx(tmp_path)
    run_fix(ctx)
    diff_path = ctx.artifact_path("patches.diff")
    assert diff_path.exists()
    diff_text = diff_path.read_text(encoding="utf-8")
    assert "---" in diff_text or "No changes" in diff_text


def test_fix_produces_valid_unified_diff(tmp_path):
    ctx = _make_ctx(tmp_path)
    run_fix(ctx)
    diff_text = ctx.artifact_path("patches.diff").read_text(encoding="utf-8")
    # Should have unified diff markers since map.json doesn't exist
    assert re.search(r"^---\s", diff_text, re.MULTILINE)
    assert re.search(r"^\+\+\+\s", diff_text, re.MULTILINE)
    assert re.search(r"^@@\s", diff_text, re.MULTILINE)


def test_fix_does_not_apply_without_flag(tmp_path):
    ctx = _make_ctx(tmp_path, apply=False)
    result = run_fix(ctx)
    assert result["applied"] is False
    assert not (tmp_path / "map.json").exists()


def test_fix_applies_with_flag_and_confirm(tmp_path):
    ctx = _make_ctx(tmp_path, apply=True, confirm=True)
    result = run_fix(ctx)
    assert result["applied"] is True
    map_path = tmp_path / "map.json"
    assert map_path.exists()
    import json

    data = json.loads(map_path.read_text(encoding="utf-8"))
    assert "files" in data
    assert "total_files" in data
    assert "python_file_count" in data


def test_fix_blocked_without_evidence(tmp_path):
    contract = tmp_path / "TASK_CONTRACT.md"
    contract.write_text(
        "# Task Contract\n\n"
        "## Goal\n\nTest.\n\n"
        "## Scope\n\nTest.\n\n"
        "## Out of scope\n\nNone.\n\n"
        "## Success Criteria\n\nPass.\n\n"
        "## Constraints\n\nNone.\n\n"
        "## Approvals required\n\nNone.\n\n"
        "## Notes\n\nNone.\n",
        encoding="utf-8",
    )
    ctx = RunContext(
        repo_root=tmp_path,
        run_id="test-noevidence",
        apply_mode=False,
        contract_path=str(contract),
    )
    ctx.ensure_run_dir()
    result = run_fix(ctx)
    assert result["errors"]
    assert any("evidence" in e.lower() for e in result["errors"])
