"""Tests for lint task type."""

from unittest.mock import patch, MagicMock
from milco.core.run_context import RunContext
from milco.core.artifacts import write_artifact
from milco.tasks.registry import get_task

import milco.tasks.lint_task  # noqa: F401


def _make_ctx(tmp_path, task_type="lint"):
    contract = tmp_path / "TASK_CONTRACT.md"
    contract.write_text(
        "# Task Contract\n\n"
        "## Task Type\n\nlint\n\n"
        "## Goal\n\nLint code.\n\n"
        "## Scope\n\nRepo.\n\n"
        "## Out of scope\n\nNone.\n\n"
        "## Success Criteria\n\nLinted.\n\n"
        "## Constraints\n\nNone.\n\n"
        "## Approvals required\n\nCONFIRM APPLY\n\n"
        "## Notes\n\nNone.\n",
        encoding="utf-8",
    )
    ctx = RunContext(
        repo_root=tmp_path,
        run_id="test-lint",
        apply_mode=False,
        contract_path=str(contract),
        task_type=task_type,
    )
    write_artifact(ctx, "evidence.md", "# Evidence\n\nSome evidence.\n")
    return ctx


def test_lint_registered():
    cls = get_task("lint")
    assert cls is not None
    assert cls.needs_llm is False
    assert "lint" in cls.description.lower() or "ruff" in cls.description.lower()


def test_lint_produces_patches_diff(tmp_path):
    ctx = _make_ctx(tmp_path)
    fake_output = "--- a/foo.py\n+++ b/foo.py\n@@ -1,2 +1,2 @@\n"
    with patch("milco.tasks.lint_task.subprocess.run") as mock_run:
        mock_run.return_value = MagicMock(returncode=1, stdout=fake_output, stderr="")
        task = get_task("lint")()
        result = task.fix(ctx)
    assert result.success is True
    assert ctx.artifact_path("patches.diff").exists()
    assert "foo.py" in ctx.artifact_path("patches.diff").read_text(encoding="utf-8")


def test_lint_no_changes_writes_placeholder(tmp_path):
    ctx = _make_ctx(tmp_path)
    with patch("milco.tasks.lint_task.subprocess.run") as mock_run:
        mock_run.return_value = MagicMock(returncode=0, stdout="", stderr="")
        task = get_task("lint")()
        result = task.fix(ctx)
    assert result.success is True
    content = ctx.artifact_path("patches.diff").read_text(encoding="utf-8")
    assert "No" in content or "lint" in content.lower()


def test_lint_blocked_without_evidence(tmp_path):
    ctx = _make_ctx(tmp_path)
    ctx.artifact_path("evidence.md").unlink(missing_ok=True)
    task = get_task("lint")()
    result = task.fix(ctx)
    assert result.success is False
    assert any("evidence" in e.lower() for e in result.errors)


def test_lint_ruff_not_found_returns_error(tmp_path):
    ctx = _make_ctx(tmp_path)
    with patch("milco.tasks.lint_task.subprocess.run") as mock_run:
        mock_run.side_effect = FileNotFoundError()
        task = get_task("lint")()
        result = task.fix(ctx)
    assert result.success is False
    assert any("ruff" in e.lower() for e in result.errors)
