"""Tests for .opencode/scripts/pipeline-status.py — NEXT_ACTIONS orchestration.

Verifies each phase's NEXT action explicitly specifies ``subagent_type`` and
``template`` (except MERGE which calls ``merge_pr`` tool directly). This makes
``pipeline_status`` the single source of truth for orchestration — the
``run-pipeline`` skill parses the ``NEXT:`` line and dispatches accordingly.
"""

import importlib.util
import sys
from pathlib import Path

import pytest

SCRIPT_PATH = (
    Path(__file__).resolve().parent.parent / ".opencode" / "scripts" / "pipeline-status.py"
)
spec = importlib.util.spec_from_file_location("pipeline_status_next_actions", SCRIPT_PATH)
ps = importlib.util.module_from_spec(spec)
sys.modules["pipeline_status_next_actions"] = ps
spec.loader.exec_module(ps)


# ── NEXT_ACTIONS: subagent_type + template per phase ─────────────────────────


@pytest.mark.parametrize(
    "phase",
    ["ISSUE", "IMPLEMENT"],
)
def test_next_action_general_subagent_template_a(phase):
    """ISSUE/IMPLEMENT → subagent_type=general, template=A."""
    action = ps.get_next_action(phase, 41)
    assert "subagent_type=general" in action
    assert "template=A" in action
    assert "PR #41" in action


def test_next_action_review_subagent_template_c():
    """REVIEW → subagent_type=reviewer, template=C."""
    action = ps.get_next_action("REVIEW", 41)
    assert "subagent_type=reviewer" in action
    assert "template=C" in action
    assert "PR #41" in action


def test_next_action_merge_pr_tool_not_subagent():
    """MERGE → merge_pr tool (NOT a subagent dispatch)."""
    action = ps.get_next_action("MERGE", 41)
    assert "merge_pr" in action
    assert "pr_number=41" in action
    assert "subagent_type" not in action
    assert "template=" not in action


def test_next_action_memory_subagent_template_e():
    """MEMORY → subagent_type=memory-syncer, template=E."""
    action = ps.get_next_action("MEMORY", 41)
    assert "subagent_type=memory-syncer" in action
    assert "template=E" in action
    assert "PR #41" in action


# ── NEXT_ACTIONS: every dispatchable phase has subagent_type ──────────────────


DISPATCH_PHASES = ["ISSUE", "IMPLEMENT", "REVIEW", "MEMORY"]


@pytest.mark.parametrize("phase", DISPATCH_PHASES)
def test_dispatch_phases_have_subagent_type(phase):
    """All dispatch phases (except MERGE) include subagent_type in NEXT action."""
    action = ps.get_next_action(phase, 41)
    assert "subagent_type=" in action, f"{phase} NEXT action missing subagent_type: {action}"


@pytest.mark.parametrize("phase", DISPATCH_PHASES)
def test_dispatch_phases_have_template(phase):
    """All dispatch phases (except MERGE) include template=X in NEXT action."""
    action = ps.get_next_action(phase, 41)
    assert "template=" in action, f"{phase} NEXT action missing template: {action}"


def test_merge_phase_does_not_dispatch_subagent():
    """MERGE is a tool call, not a subagent dispatch — no subagent_type/template."""
    action = ps.get_next_action("MERGE", 41)
    assert "subagent_type" not in action
    assert "template=" not in action
    assert "merge_pr" in action


# ── NEXT_ACTIONS: pr_number substitution ──────────────────────────────────────


@pytest.mark.parametrize(
    ("phase", "pr_number"),
    [("ISSUE", 1), ("REVIEW", 42), ("MERGE", 7), ("MEMORY", 100)],
)
def test_next_action_pr_number_substitution(phase, pr_number):
    """``N`` placeholder in NEXT_ACTIONS is replaced with the actual PR number."""
    action = ps.get_next_action(phase, pr_number)
    assert str(pr_number) in action
    # The literal "N" placeholder must not survive substitution.
    assert " PR #N" not in action
    assert "pr_number=N" not in action


# ── REVIEW verdict branching still uses subagent_type ─────────────────────────


def test_review_request_changes_dispatches_general_subagent():
    """REVIEW REQUEST_CHANGES → fix subagent (general), not re-run reviewer."""
    result = ps.PhaseResult(ps.PhaseStatus.NOT_DONE, "verdict: REQUEST_CHANGES")
    action = ps.get_next_action_review(result)
    assert "subagent_type=general" in action
    assert "fix reviewer comments" in action


def test_review_default_dispatches_reviewer_subagent():
    """REVIEW default (no verdict) → dispatch reviewer subagent (template C)."""
    result = ps.PhaseResult(ps.PhaseStatus.NOT_DONE, "нет комментариев PR")
    action = ps.get_next_action_review(result)
    assert "subagent_type=reviewer" in action
    assert "template=C" in action


def test_review_needs_discussion_no_subagent():
    """REVIEW NEEDS_DISCUSSION → clarification, not a subagent dispatch."""
    result = ps.PhaseResult(ps.PhaseStatus.NOT_DONE, "verdict: NEEDS_DISCUSSION")
    action = ps.get_next_action_review(result)
    assert "уточни вопросы" in action
    assert "subagent_type" not in action
