"""Confirmatory launcher — freeze guard + human-gate hold (no data collected).

The live preflight is exercised by the gate/battery/grid suites; here we pin the
guard logic: the frozen-prereg SHA verifies, GO is refused without the operator
token, a tokened GO holds on grid completion (3rd phone not up yet), and even a
full grid holds for the operator rather than fabricating the data run.
"""

from cmd_chat.sor import confirmatory_run as cr


# A fully-ready preflight summary with the grid still completing (a device down).
_READY_GRID_DOWN = {
    "out_dir": "x", "gate_all_green": True, "gate_offline_green": True,
    "grid_reachable": 2, "grid_engine_hosts": 1, "grid_down": ["tril"],
    "grid_honourable": True, "grid_full": False, "cell_plan": "p", "dry_ok": True,
    "assembler_ok": True, "assembler_distinct": True, "assembler_isolation_gated": True,
    "freeze_ok": True, "preflight_ready": True, "generated_utc": "now",
}
# The same, but with the full grid up (no device down).
_READY_GRID_FULL = dict(_READY_GRID_DOWN, grid_down=[], grid_full=True)


def test_frozen_prereg_sha_verifies():
    assert cr.verify_freeze() is True  # on-disk prereg still matches the pin


def test_go_refused_without_operator_token(monkeypatch):
    monkeypatch.setattr(cr, "preflight", lambda *a, **k: dict(_READY_GRID_DOWN))
    monkeypatch.delenv(cr.OPERATOR_TOKEN_ENV, raising=False)
    assert cr.main(["--operator-go", "--out", "x"]) == 2


def test_go_holds_on_grid_completion(monkeypatch):
    monkeypatch.setattr(cr, "preflight", lambda *a, **k: dict(_READY_GRID_DOWN))
    monkeypatch.setattr(cr, "verify_freeze", lambda: True)
    monkeypatch.setenv(cr.OPERATOR_TOKEN_ENV, "1")
    # Triple-lock + green preflight + wired assembler, but grid still completing.
    assert cr.main(["--operator-go", "--out", "x"]) == 2


def test_go_collects_on_full_grid_with_token(monkeypatch):
    monkeypatch.setattr(cr, "preflight", lambda *a, **k: dict(_READY_GRID_FULL))
    monkeypatch.setattr(cr, "verify_freeze", lambda: True)
    monkeypatch.setenv(cr.OPERATOR_TOKEN_ENV, "1")
    # Stub the live executor so the unit test does not stand up docker; assert the
    # GO path actually invokes the real data collector with live=True.
    from cmd_chat.sor import executor
    calls = {}

    def _fake_run_battery(out_root, **kw):
        calls.update(kw)
        calls["out_root"] = str(out_root)
        return {"n_runs": 180, "measured_from": "live-docker-pcap",
                "_results_path": str(out_root) + "/battery-results.json"}

    monkeypatch.setattr(executor, "run_battery", _fake_run_battery)
    # Full grid + all three locks + token: collect for real (returns 0).
    assert cr.main(["--operator-go", "--out", "x"]) == 0
    assert calls["live"] is True  # never a dry/synthetic confirmatory path


def test_go_executor_refusal_never_fabricates(monkeypatch):
    monkeypatch.setattr(cr, "preflight", lambda *a, **k: dict(_READY_GRID_FULL))
    monkeypatch.setattr(cr, "verify_freeze", lambda: True)
    monkeypatch.setenv(cr.OPERATOR_TOKEN_ENV, "1")
    from cmd_chat.sor import executor

    def _refuse(out_root, **kw):
        raise executor.ExecutorError("no real pcap measurement available")

    monkeypatch.setattr(executor, "run_battery", _refuse)
    # If the executor cannot measure real data it refuses; the launcher surfaces
    # that as a NO-GO (2) rather than emitting a fabricated DV.
    assert cr.main(["--operator-go", "--out", "x"]) == 2


def test_preflight_held_mode_returns_zero(monkeypatch):
    monkeypatch.setattr(cr, "preflight", lambda *a, **k: dict(_READY_GRID_DOWN))
    assert cr.main(["--out", "x"]) == 0  # no --operator-go: held, no data
