"""ORCH-076 (ORCH-52c): anti-regression for the five verdict gates after the parse
is delegated to the unified frontmatter API.

Covers TC-08..TC-15 of docs/work-items/ORCH-076/04-test-plan.yaml. The MECHANISM of
YAML-frontmatter parsing is now centralised in ``src/frontmatter.parse_frontmatter``,
but the verdict SEMANTICS (value -> transition) must be 1:1 with before the task:
  * check_reviewer_verdict  (12-review.md, verdict:)              — TC-08
  * _parse_tests_verdict    (13-test-report.md, result/verdict/status, ORCH-047) — TC-09
  * _parse_deploy_status    (14-deploy-log.md, deploy_status:)    — TC-10
  * _parse_staging_status   (15-staging-log.md, staging_status:)  — TC-11
  * (parse_security_status is exercised in tests/test_security_gate.py — TC-12)
  * backward-compat of old docs (no new schema) + additive schema  — TC-13 / TC-14
  * worktree -> origin/main fallback preserved                     — TC-15
"""

import os
import tempfile

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

from src.qg import checks as qg  # noqa: E402
from src.qg.checks import (  # noqa: E402
    _parse_deploy_status,
    _parse_staging_status,
    _parse_tests_verdict,
    check_deploy_status,
    check_reviewer_verdict,
    check_staging_status,
)


def _write(dirpath, work_item_id, name, content):
    d = os.path.join(dirpath, "docs", "work-items", work_item_id)
    os.makedirs(d, exist_ok=True)
    with open(os.path.join(d, name), "w", encoding="utf-8") as f:
        f.write(content)


# --------------------------------------------------------------------------- #
# TC-08 — check_reviewer_verdict via the unified API.
# --------------------------------------------------------------------------- #
def test_tc08_reviewer_verdict_semantics(monkeypatch):
    with tempfile.TemporaryDirectory() as d:
        monkeypatch.setattr(qg, "_repo_path", lambda repo, branch=None: d)
        _write(d, "ORCH-1", "12-review.md", "---\nverdict: APPROVED\n---\nbody")
        ok, reason = check_reviewer_verdict("orchestrator", "ORCH-1")
        assert ok is True and "APPROVED" in reason

        _write(d, "ORCH-1", "12-review.md", "---\nverdict: REQUEST_CHANGES\n---\nbody")
        ok, reason = check_reviewer_verdict("orchestrator", "ORCH-1")
        assert ok is False and "REQUEST_CHANGES" in reason

        # Missing verdict key -> (False).
        _write(d, "ORCH-1", "12-review.md", "---\nother: x\n---\nbody")
        ok, _ = check_reviewer_verdict("orchestrator", "ORCH-1")
        assert ok is False

        # No frontmatter at all -> (False).
        _write(d, "ORCH-1", "12-review.md", "# review\nAPPROVED in prose\n")
        ok, _ = check_reviewer_verdict("orchestrator", "ORCH-1")
        assert ok is False


# --------------------------------------------------------------------------- #
# TC-09 — _parse_tests_verdict: ORCH-047 three equal-rank fields + negative-token
#         priority preserved.
# --------------------------------------------------------------------------- #
def test_tc09_tests_three_fields_each_pass():
    for field in ("result", "verdict", "status"):
        ok, reason = _parse_tests_verdict(f"---\n{field}: PASS\n---\nbody")
        assert ok is True, field
        assert "PASS" in reason


def test_tc09_negative_token_is_authoritative():
    # BLOCKED in one field beats a positive token in another (ET-013 case).
    ok, reason = _parse_tests_verdict("---\nverdict: BLOCKED\nstatus: PASS\n---\n")
    assert ok is False
    assert "BLOCKED" in reason
    # FAIL likewise.
    ok, _ = _parse_tests_verdict("---\nresult: FAIL\n---\n")
    assert ok is False


def test_tc09_tests_no_frontmatter_and_malformed():
    ok, reason = _parse_tests_verdict("no frontmatter, 23 passed\n")
    assert ok is False and "No YAML frontmatter" in reason
    ok, reason = _parse_tests_verdict("---\nresult: PASS\nunterminated")
    assert ok is False and "Malformed" in reason
    ok, reason = _parse_tests_verdict("---\nresult: PASS\nempty:\n---\n")
    assert ok is True  # result PASS still wins; empty other field is fine


# --------------------------------------------------------------------------- #
# TC-10 — _parse_deploy_status semantics (БАГ-8) unchanged.
# --------------------------------------------------------------------------- #
def test_tc10_deploy_status_semantics():
    assert _parse_deploy_status("---\ndeploy_status: SUCCESS\n---\n")[0] is True
    assert _parse_deploy_status("---\ndeploy_status: FAILED\n---\n")[0] is False
    assert _parse_deploy_status("---\nother: SUCCESS\n---\n")[0] is False
    assert _parse_deploy_status("prose only SUCCESS")[0] is False
    # Bad YAML -> (False) with the preserved reason prefix.
    ok, reason = _parse_deploy_status("---\nx: : :\n---\n")
    assert ok is False and "Invalid YAML frontmatter in deploy log" in reason


# --------------------------------------------------------------------------- #
# TC-11 — _parse_staging_status + ORCH-35 conditionality (non-self -> N/A pass).
# --------------------------------------------------------------------------- #
def test_tc11_staging_status_semantics():
    assert _parse_staging_status("---\nstaging_status: SUCCESS\n---\n")[0] is True
    assert _parse_staging_status("---\nstaging_status: FAILED\n---\n")[0] is False
    assert _parse_staging_status("---\nother: SUCCESS\n---\n")[0] is False


def test_tc11_staging_gate_na_for_non_self():
    ok, reason = check_staging_status("enduro-trails", "ET-1", "feature/x")
    assert ok is True
    assert "N/A" in reason


# --------------------------------------------------------------------------- #
# TC-13 — old verdict docs WITHOUT the new schema read exactly as before, for
#         every parser.
# --------------------------------------------------------------------------- #
def test_tc13_old_docs_without_schema_still_read():
    # None of these carry work_item/stage/author_agent/status/created_at/model_used.
    assert _parse_tests_verdict("---\nresult: PASS\n---\n")[0] is True
    assert _parse_tests_verdict("---\nverdict: FAIL\n---\n")[0] is False
    assert _parse_deploy_status("---\ndeploy_status: SUCCESS\n---\n")[0] is True
    assert _parse_staging_status("---\nstaging_status: SUCCESS\n---\n")[0] is True


def test_tc13_reviewer_old_doc(monkeypatch):
    with tempfile.TemporaryDirectory() as d:
        monkeypatch.setattr(qg, "_repo_path", lambda repo, branch=None: d)
        _write(d, "ORCH-1", "12-review.md", "---\nverdict: APPROVED\n---\nlegacy body")
        assert check_reviewer_verdict("orchestrator", "ORCH-1")[0] is True


# --------------------------------------------------------------------------- #
# TC-14 — a doc WITH the full additive schema + verdict key yields the SAME
#         verdict as without the schema (schema is additive, never changes it).
# --------------------------------------------------------------------------- #
_SCHEMA = (
    "work_item: ORCH-076\nstage: testing\nauthor_agent: tester\n"
    "status: PASS\ncreated_at: 2026-06-09\nmodel_used: claude-opus-4-8\n"
)


def test_tc14_full_schema_does_not_change_verdict():
    bare = _parse_tests_verdict("---\nresult: PASS\n---\n")
    full = _parse_tests_verdict(f"---\n{_SCHEMA}result: PASS\n---\n")
    assert bare[0] == full[0] is True

    bare_d = _parse_deploy_status("---\ndeploy_status: FAILED\n---\n")
    full_d = _parse_deploy_status(
        "---\nwork_item: ORCH-076\nstage: deploy\nauthor_agent: deployer\n"
        "status: done\ncreated_at: 2026-06-09\nmodel_used: claude-opus-4-8\n"
        "deploy_status: FAILED\n---\n"
    )
    assert bare_d[0] == full_d[0] is False


def test_tc14_reviewer_with_schema(monkeypatch):
    with tempfile.TemporaryDirectory() as d:
        monkeypatch.setattr(qg, "_repo_path", lambda repo, branch=None: d)
        _write(
            d, "ORCH-1", "12-review.md",
            "---\nwork_item: ORCH-1\nstage: review\nauthor_agent: reviewer\n"
            "status: APPROVED\ncreated_at: 2026-06-09\nmodel_used: claude-opus-4-8\n"
            "verdict: APPROVED\n---\nbody",
        )
        assert check_reviewer_verdict("orchestrator", "ORCH-1")[0] is True


# --------------------------------------------------------------------------- #
# TC-15 — fallback worktree -> origin/main preserved (the gate still reads the
#         log recovered from main through the unified parser).
# --------------------------------------------------------------------------- #
def test_tc15_deploy_status_origin_main_fallback(monkeypatch):
    with tempfile.TemporaryDirectory() as d:
        # No 14-deploy-log.md in the worktree -> the gate must consult origin/main.
        monkeypatch.setattr(qg, "_repo_path", lambda repo, branch=None: d)
        monkeypatch.setattr(
            qg, "_deploy_log_from_main",
            lambda repo, wi: "---\ndeploy_status: SUCCESS\n---\nfrom main",
        )
        ok, reason = check_deploy_status("orchestrator", "ORCH-1", "feature/x")
        assert ok is True and "SUCCESS" in reason


def test_tc15_staging_status_origin_main_fallback(monkeypatch):
    with tempfile.TemporaryDirectory() as d:
        monkeypatch.setattr(qg, "_repo_path", lambda repo, branch=None: d)
        monkeypatch.setattr(
            qg, "_staging_log_from_main",
            lambda repo, wi: "---\nstaging_status: FAILED\n---\nfrom main",
        )
        ok, reason = check_staging_status("orchestrator", "ORCH-1", "feature/x")
        assert ok is False and "FAILED" in reason
