"""R4 (e2e half) — 3-hop nested-SSH circuit delivery acceptance check.

Acceptance predicate (instrument-validation gate item 1, the traffic-moving half
of roadmap R4): a >=3-hop self-traffic circuit of *isolated* containers delivers
a known, seed-deterministic payload end-to-end, and a per-hop pcap exists and
checksums. This suite drives the real ``run_circuit_fixture`` against a live
docker engine and asserts exactly that conjunct.

Containment is still law here: the runner refuses ``local``/unknown engines up
front (re-checked offline below), only self-generated fixture bytes move, they
move only between our own containers on our own engine, and the circuit is always
torn down. The e2e cell needs a live docker daemon + the ``sor-hop`` image; it is
skipped (not failed) where either is absent, so the offline suite stays green on
any host.
"""

import shutil
import subprocess

import pytest

from cmd_chat.sor.config import Domain, SorRng
from cmd_chat.sor.forwarder import (
    HOP_IMAGE,
    CircuitError,
    _seed_payload,
    run_circuit_fixture,
)


def _docker_ready() -> bool:
    if shutil.which("docker") is None:
        return False
    try:
        subprocess.run(["docker", "info"], capture_output=True, timeout=15, check=True)
    except Exception:
        return False
    return True


def _image_present() -> bool:
    try:
        out = subprocess.run(
            ["docker", "image", "inspect", HOP_IMAGE],
            capture_output=True, timeout=15, check=False,
        )
    except Exception:
        return False
    return out.returncode == 0


live = pytest.mark.skipif(
    not (_docker_ready() and _image_present()),
    reason="requires a live docker daemon and the sor-hop:latest image",
)


# --------------------------------------------------------------------------- #
# Offline: containment refusals hold even for the e2e entry point.
# --------------------------------------------------------------------------- #
def test_e2e_refuses_local_engine():
    with pytest.raises(Exception):
        run_circuit_fixture(1, engine="local")


def test_e2e_refuses_non_docker_isolated_engine():
    # multipass is isolated but the e2e runner is only wired for docker.
    with pytest.raises(CircuitError):
        run_circuit_fixture(1, engine="multipass")


def test_e2e_refuses_fewer_than_three_hops():
    with pytest.raises(CircuitError):
        run_circuit_fixture(1, engine="docker", hops=2)


def test_seed_payload_is_deterministic_self_traffic():
    # Same seed -> identical fixture bytes (no real data); different seed differs.
    assert _seed_payload(42) == _seed_payload(42)
    assert _seed_payload(42) != _seed_payload(43)
    # It is exactly the R1 PADDING stream (self-generated, reproducible).
    stream = SorRng(42).stream(Domain.PADDING)
    assert _seed_payload(42, 16) == bytes(stream.next_below(256) for _ in range(16))


# --------------------------------------------------------------------------- #
# Gate item 1 — the live conjunct.
# --------------------------------------------------------------------------- #
@live
def test_three_hop_circuit_delivers_and_checksums(tmp_path):
    seed = 0xC0FFEE
    result = run_circuit_fixture(seed, engine="docker", hops=3, out_root=tmp_path)

    # (a) end-to-end delivery of the known payload.
    assert result.delivered is True
    assert result.received_sha256 == result.payload_sha256

    # (b) a per-hop pcap exists and checksums (3 distinct hops).
    assert set(result.pcaps.keys()) == {0, 1, 2}
    for i in (0, 1, 2):
        pcap = result.pcaps[i]
        assert pcap.exists() and pcap.stat().st_size > 0
        assert len(result.pcap_sha256[i]) == 64

    # (c) provenance: the R3 event log was sealed.
    assert result.events_sha256 and len(result.events_sha256) == 64

    # (d) containment: three distinct isolated containers, engine never local.
    assert result.engine == "docker"
    assert len(set(result.hop_containers)) == 3
