"""Contract: the broker's ``reconcile`` wire op + ``Client.reconcile_after_restart``
(Tier-1 #8 restart-recovery wiring, R-T1-8-RESTART-WIRING).

The broker re-derives truth after a restart from two authoritative sources — what
each worker's backend enumerates as present in hardware, and the live-client lease
table — and quarantines every resource that is present-but-unclaimed
(``unclaimed_after_restart``). The per-core mechanism is pinned in Zig
(``core_test.zig``); the broker-wide enumerate→reconcile fan-out in
``facade_test.zig``. Here we pin the wire op end-to-end + its authority gate.

These tests scope reconcile to the FakeBackend's ``hw:/test/**`` namespace so they
never touch the host's real PCI/USB hardware. The ``broker`` fixture is
function-scoped (a fresh broker per test), so quarantining the fake test devices
can't contaminate any other test.
"""

from __future__ import annotations

from typing import TYPE_CHECKING

import pytest

from mgf.hrb.exceptions import MgfHrbError

if TYPE_CHECKING:
    from mgf.hrb import Client


def test_reconcile_quarantines_present_unclaimed_orphans(broker: Client) -> None:
    """A live lease survives the reconcile; every other present-in-hardware
    device in scope is quarantined (orphaned by the restart) and is then
    refused for claim until recovered."""
    held = "hw:/test/dev0"
    lease = broker.claim(held)  # a "live client" holding a device across the restart

    res = broker.reconcile_after_restart(scope="hw:/test/**")
    assert res["ok"] is True
    # The fake worker seeds dev0 + dev1 + edge_attrs → at least 3 present.
    assert res["scanned"] >= 3
    # dev0 is held (live lease) → NOT quarantined; the rest are orphans.
    assert res["quarantined"] >= 1
    assert res["truncated"] is False

    # An orphaned (present-but-unclaimed) device is now quarantined → refused.
    with pytest.raises(MgfHrbError):
        broker.claim("hw:/test/dev1")

    # ...and it recovers back to Free via the reset-escalation ladder (#12).
    outcome = broker.recover("hw:/test/dev1")
    assert outcome in ("recovered_flr", "recovered_bus")

    # The device I held was untouched (live lease respected) — release succeeds.
    lease.release()


def test_reconcile_is_idempotent(broker: Client) -> None:
    """A second reconcile over the same scope quarantines nothing new — the
    contract is re-derivation, so re-running is safe (an operator can retry)."""
    first = broker.reconcile_after_restart(scope="hw:/test/**")
    assert first["ok"] is True
    assert first["quarantined"] >= 1
    second = broker.reconcile_after_restart(scope="hw:/test/**")
    assert second["ok"] is True
    assert second["quarantined"] == 0  # all orphans already quarantined


def test_reconcile_requires_authority_over_scope(broker: Client) -> None:
    """The op is steal-gated on the requested scope: a cap attenuated to a
    narrow sub-scope cannot reconcile a broader namespace it has no authority
    over (the same operator-class gate as ``recover``/``revoke``)."""
    narrow = broker.attenuate(scope="hw:/test/dev0")
    try:
        # The narrow cap covers only hw:/test/dev0 — it can't reconcile hw:/**.
        with pytest.raises(MgfHrbError):
            narrow.reconcile_after_restart(scope="hw:/**")
    finally:
        narrow.close()
