"""ORCH-019 — composition with ORCH-088 serial-gate / ORCH-089 auto-label (AC-9).

Covers (04-test-plan.yaml):
  TC-14  A bug-fast-track task is an ORDINARY repo task for the serial gate
         (ORCH-088): it counts as an active task and is gated like any other — it
         does NOT bypass serialisation. autoApprove/autoDeploy (ORCH-089) apply on
         the bug track (scope is repo-based, track-agnostic).
"""
import os
import tempfile

import pytest

os.environ["ORCH_DB_PATH"] = os.path.join(tempfile.gettempdir(), "test_bft_composition.db")
os.environ.setdefault("ORCH_GITEA_TOKEN", "test-token")
os.environ.setdefault("ORCH_PLANE_API_TOKEN", "test-token")

import src.db as db  # noqa: E402
from src.db import init_db, get_db, enqueue_job, claim_next_job  # noqa: E402
from src import serial_gate, labels, config as cfg  # noqa: E402


@pytest.fixture(autouse=True)
def fresh_db(tmp_path, monkeypatch):
    dbfile = tmp_path / "comp.db"
    monkeypatch.setattr(db.settings, "db_path", str(dbfile))
    monkeypatch.setattr(cfg.settings, "serial_gate_enabled", True, raising=False)
    monkeypatch.setattr(cfg.settings, "serial_gate_repos", "", raising=False)
    monkeypatch.setattr(cfg.settings, "serial_gate_freeze_enabled", False, raising=False)
    monkeypatch.setattr(cfg.settings, "task_deps_enabled", False, raising=False)
    monkeypatch.setattr(cfg.settings, "bug_fast_track_enabled", True, raising=False)
    monkeypatch.setattr(cfg.settings, "auto_label_enabled", True, raising=False)
    init_db()
    yield


def _make_task(work_item_id, stage="analysis", repo="orchestrator", track="full"):
    conn = get_db()
    cur = conn.execute(
        "INSERT INTO tasks (plane_id, work_item_id, repo, branch, stage, title, track) "
        "VALUES (?, ?, ?, ?, ?, ?, ?)",
        (work_item_id, work_item_id, repo, f"feature/{work_item_id}", stage, work_item_id, track),
    )
    tid = cur.lastrowid
    conn.commit()
    conn.close()
    return tid


def test_tc14_bug_task_counts_as_active_in_serial_gate():
    # An EARLIER bug task A (unfinished) must gate a later task B's analyst-job —
    # a bug task does NOT bypass the serial gate.
    _make_task("ORCH-301", stage="development", track="bug")     # active bug predecessor
    b = _make_task("ORCH-302", stage="analysis", track="full")   # new task
    enqueue_job("analyst", "orchestrator", "B", task_id=b)
    assert claim_next_job() is None, "a bug task must gate a later analyst-job (no bypass)"
    # The bug task is the active task in the snapshot.
    per = serial_gate.snapshot()["per_repo"]["orchestrator"]
    assert per["active_task"]["work_item_id"] == "ORCH-301"


def test_tc14_bug_task_itself_gated_behind_predecessor():
    # The bug task is also HELD behind an earlier non-bug task (symmetry).
    _make_task("ORCH-310", stage="development", track="full")    # active predecessor
    b = _make_task("ORCH-311", stage="analysis", track="bug")    # new BUG task
    enqueue_job("analyst", "orchestrator", "bug-B", task_id=b)
    assert claim_next_job() is None, "a bug task is itself serialised behind the predecessor"


def test_tc14_bug_task_claimable_once_predecessor_done():
    a = _make_task("ORCH-320", stage="development", track="full")
    b = _make_task("ORCH-321", stage="analysis", track="bug")
    jid = enqueue_job("analyst", "orchestrator", "bug-B", task_id=b)
    assert claim_next_job() is None
    # Finish A -> the bug task's analyst-job is now claimable.
    conn = get_db()
    conn.execute("UPDATE tasks SET stage='done' WHERE id=?", (a,))
    conn.commit()
    conn.close()
    claimed = claim_next_job()
    assert claimed is not None and claimed["id"] == jid


def test_tc14_auto_label_applies_track_agnostic(monkeypatch):
    # autoApprove/autoDeploy scope is repo-based, independent of the bug track.
    assert labels.auto_approve_applies("orchestrator") is True
    assert labels.auto_deploy_applies("orchestrator") is True
