"""ORCH-016 / TC-16 + AC-6: analyst status-only regression.

Status-only verdict model (PR #12 / #13):
  - analyst finishes its run -> Plane state becomes In Review,
  - ONE status comment is posted asking the stakeholder to flip the status to
    Approved (or write a reason and switch to Rejected),
  - NO auto-advance happens — the next stage waits for human approval.

The ORCH-016 PR refactors the comment text into the unified status-comment
helper. This regression test guards against:
  (a) the analyst path silently auto-advancing,
  (b) the analyst comment losing the «Approved» / «Rejected» instruction text,
  (c) the comment switching authorship away from the analyst bot.

We exercise `_handle_analysis_approved_flow` directly (the launcher path).
"""

import os
import tempfile

os.environ.setdefault("ORCH_PLANE_API_TOKEN", "test-token")
os.environ.setdefault("ORCH_GITEA_TOKEN", "test-token")

_test_db = os.path.join(tempfile.gettempdir(), "test_orch016_analyst_so.db")
os.environ["ORCH_DB_PATH"] = _test_db

import pytest  # noqa: E402

from src import db as db_module  # noqa: E402
from src.db import init_db, get_db  # noqa: E402


REPO = "enduro-trails"
BRANCH = "feature/ET-016-x"
WID = "ET-016"


@pytest.fixture(autouse=True)
def setup_db(monkeypatch, tmp_path):
    monkeypatch.setattr(db_module.settings, "db_path", _test_db, raising=False)
    if os.path.exists(_test_db):
        os.unlink(_test_db)
    init_db()
    conn = get_db()
    conn.execute(
        "INSERT INTO tasks (id, repo, branch, stage, work_item_id) "
        "VALUES (1, ?, ?, 'analysis', ?)",
        (REPO, BRANCH, WID),
    )
    conn.commit()
    conn.close()
    yield
    if os.path.exists(_test_db):
        os.unlink(_test_db)


@pytest.fixture
def fake_worktree(monkeypatch, tmp_path):
    base = tmp_path / "wt"
    docs = base / "docs" / "work-items" / WID
    docs.mkdir(parents=True)
    # All analyst artifacts present -> "files_check" returns True.
    for f in ("01-brd.md", "02-trz.md", "03-acceptance-criteria.md",
              "04-test-plan.yaml"):
        (docs / f).write_text("x")
    monkeypatch.setattr("src.git_worktree.get_worktree_path", lambda r, b: str(base))
    monkeypatch.setattr("src.stage_engine.get_worktree_path", lambda r, b: str(base))
    monkeypatch.setattr("src.qg.checks.get_worktree_path", lambda r, b: str(base))
    return base


@pytest.fixture
def collect_calls(monkeypatch):
    calls = {"in_review": 0, "advance": 0, "comments": [], "enqueued": []}

    monkeypatch.setattr(
        "src.stage_engine.set_issue_in_review",
        lambda wid: calls.__setitem__("in_review", calls["in_review"] + 1),
    )
    monkeypatch.setattr(
        "src.stage_engine.notify_approve_requested", lambda tid: None
    )

    def _add_comment(wid, body, author=None, **kw):
        calls["comments"].append({"wid": wid, "body": body, "author": author})

    monkeypatch.setattr("src.stage_engine.plane_add_comment", _add_comment)

    # advance_stage isn't directly hit; if anything calls update_task_stage to
    # 'architecture', we'd see it here.
    def _update_task_stage(task_id, stage):
        calls["advance"] += 1

    monkeypatch.setattr("src.stage_engine.update_task_stage", _update_task_stage)

    def _enqueue(*a, **k):
        calls["enqueued"].append((a, k))
        return 1

    monkeypatch.setattr("src.stage_engine.enqueue_job", _enqueue)
    return calls


def test_tc16_analyst_goes_to_in_review_no_advance(fake_worktree, collect_calls):
    """When the analyst finishes with complete artifacts, the task goes to In
    Review and NO advance/enqueue happens — the human approves via Plane status.
    """
    from src.stage_engine import _handle_analysis_approved_flow, AdvanceResult

    result = AdvanceResult(from_stage="analysis")
    _handle_analysis_approved_flow(
        task_id=1, current_stage="analysis", repo=REPO, work_item_id=WID,
        branch=BRANCH, agent="analyst", result=result,
    )

    # In Review state requested in Plane.
    assert collect_calls["in_review"] == 1, collect_calls
    # NO stage-machine advance.
    assert collect_calls["advance"] == 0, collect_calls
    # NO new job enqueued by the analyst path.
    assert collect_calls["enqueued"] == [], collect_calls

    # Exactly one comment posted, authored by analyst, with required text bits.
    assert len(collect_calls["comments"]) == 1, collect_calls["comments"]
    c = collect_calls["comments"][0]
    assert c["wid"] == WID
    assert c["author"] == "analyst"
    body = c["body"]
    assert "Approved" in body
    assert "Rejected" in body
    assert ":approved:" not in body
    assert "In Progress" not in body
    # AC-6 +: the new unified format adds a Длительность line (DB fallback).
    # No agent_runs row exists in this test, so the line should be ABSENT.
    assert "Длительность" not in body
