"""03 — identity-continuity comparator: pure SDK, no broker required.

Capture a Snapshot before a mode change, then ask whether a candidate
post-change Snapshot is the same physical unit. This is the comparator
the recipe `track-a-device-across-a-mode-change.md` documents — useful
for VFIO passthrough flows that span a DFU sequence, USB hub replug,
etc.

Companion recipe: ../recipes/track-a-device-across-a-mode-change.md
"""

from __future__ import annotations

from mgf.hrb import (
    Confidence,
    IdentityClass,
    Snapshot,
    same_likely,
    same_likely_explained,
)


def main() -> int:
    # An iFig device in Recovery mode (the case validated against in
    # mgf-usb v0.2.5 — see hrb-design/mgf-hrb-usb-worker.md §4.3).
    recovery = Snapshot(
        urn="hw:/usb/bus1/port-2.3/dev/if0",
        identity_class=IdentityClass.INTRINSIC,
        vid=0x05AC,
        pid=0x1281,
        serial_number="F4GS9PWWJCM7",
        bus=1,
        port_chain=(2, 3),
        captured_at_ms=1_000,
    )

    # Same physical iFig moments later, in DFU mode: PID flipped, serial
    # vanished (some firmware drops iSerial in DFU), port stayed.
    dfu = Snapshot(
        urn="hw:/usb/bus1/port-2.3/dev/if0",
        identity_class=IdentityClass.TOPOLOGICAL,
        vid=0x05AC,
        pid=0x1227,
        serial_number=None,
        bus=1,
        port_chain=(2, 3),
        captured_at_ms=1_500,  # 500 ms later, inside the default debounce
    )

    print("Confidence verdict:", same_likely(recovery, dfu).name)
    # → LIKELY_SAME (score 11 per the spec; see hrb-design/mgf-hrb-usb-worker.md §4.3)

    # The explained form shows every scored signal — handy for debugging
    # "why didn't this match?" or pinning a flaky test.
    explained = same_likely_explained(recovery, dfu)
    print(f"Score: {explained.score}")
    print("Signals:")
    for contribution in explained.contributions:
        sign = "+" if contribution.score >= 0 else ""
        print(f"  {sign}{contribution.score:+d}  {contribution.label}")

    # A consumer's policy: only proceed if at least LIKELY_SAME.
    if explained.confidence >= Confidence.LIKELY_SAME:
        print("Decision: proceed (same physical unit).")
        return 0
    print("Decision: do NOT proceed (identity not confident enough).")
    return 1


if __name__ == "__main__":
    raise SystemExit(main())
