#!/usr/bin/env bash
# Verify EtherGold EG 2.2 BOM + IPC layout on this Pi.
# Called from hat_fixture_bridge.sh / legacy run_bridge.sh.

set -euo pipefail
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
cd "${ROOT}"

python3 <<'PY'
import struct
import sys

import pog422_fixture_core as core
from pog422_uart_capture import UartCaptureHandler, resolve_uartd_enabled
from pog422_uart_client import (
    IPC_INJECT_FORENSICS,
    POG422_EG_VERSION,
    POG422_UARTD_VERSION,
    _GPIO7_ACK,
    _HAT_REGS,
    _INJECT_DONE,
    _INJECT_FORENSICS_DE,
    _INJECT_FORENSICS_HDR,
)

errors: list[str] = []

if not str(core.FIXTURE_PARSER_BUILD).startswith(f"eg-{core.EG_VERSION}"):
    errors.append(f"FIXTURE_PARSER_BUILD={core.FIXTURE_PARSER_BUILD!r}")

# Client stamps may lag Python tip; only require the configured component range.
for label, ver in (
    ("POG422_EG_VERSION", POG422_EG_VERSION),
    ("POG422_UARTD_VERSION", POG422_UARTD_VERSION),
):
    if not core.eg_version_in_range(ver):
        errors.append(
            f"{label}={ver!r} not in "
            f"[{core.EG_COMPONENT_MIN_VERSION}, {core.EG_COMPONENT_MAX_VERSION}]"
        )

if not hasattr(core, "inject_forensics_event_fields"):
    errors.append("inject_forensics_event_fields missing from pog422_fixture_core")

if not hasattr(core, "arm_post_x9_inject_grace"):
    errors.append("arm_post_x9_inject_grace missing from pog422_fixture_core")

if IPC_INJECT_FORENSICS != 10:
    errors.append(f"IPC_INJECT_FORENSICS={IPC_INJECT_FORENSICS}")

if _INJECT_FORENSICS_HDR.size != 40:
    errors.append(f"inject_forensics hdr size {_INJECT_FORENSICS_HDR.size} != 40")

if _INJECT_FORENSICS_DE.size != 8:
    errors.append(f"inject_forensics DE trailer size {_INJECT_FORENSICS_DE.size} != 8")

if not hasattr(core, "probe_hat_session"):
    errors.append("probe_hat_session missing from pog422_fixture_core")

if not hasattr(core, "B142X_UART_CHANNELS"):
    errors.append("B142X_UART_CHANNELS missing from pog422_fixture_core")

if not hasattr(UartCaptureHandler, "drain"):
    errors.append("UartCaptureHandler.drain missing")

if resolve_uartd_enabled(type("A", (), {"no_uartd": False, "uartd": False})(), default=True) is not True:
    errors.append("resolve_uartd_enabled default=True broken")

_ipc_hdr = struct.Struct("<QQQI")
if _ipc_hdr.size != 28:
    errors.append(f"IPC window header wire size {_ipc_hdr.size} != 28")

if not hasattr(core, "resolve_transparent_bridge"):
    errors.append("resolve_transparent_bridge missing from pog422_fixture_core")

if not hasattr(core.EventLog, "set_uart_segment_handler"):
    errors.append("EventLog.set_uart_segment_handler missing")

if not hasattr(core.DirectionalEthRouter, "send_eth_to_peers"):
    errors.append("DirectionalEthRouter.send_eth_to_peers missing")

if not hasattr(core.DirectionalEthRouter, "reopen_port"):
    errors.append("DirectionalEthRouter.reopen_port missing")

errors.extend(core.parser_self_test())

if _INJECT_DONE.size != 39:
    errors.append(f"inject_done size {_INJECT_DONE.size} != 39")

if _GPIO7_ACK.size != 6:
    errors.append(f"gpio7_ack size {_GPIO7_ACK.size} != 6")

if _HAT_REGS.size != 20:
    errors.append(f"hat_regs size {_HAT_REGS.size} != 20")

# EG 2.1 inject req: pre, post, flush, require_idle, idle_wait_ms, frame_len
hdr = struct.pack("<IIBBHI", 0, 0, 0, 1, 80, 32)
if len(hdr) != 16:
    errors.append(f"inject req hdr len {len(hdr)} != 16")

srb = core.build_fixture_ctrl(core.FIXTURE_CMD_SRB_ASSERT, 3)
if core.parse_fixture_ctrl(srb) != (core.FIXTURE_CMD_SRB_ASSERT, 3):
    errors.append(f"fixture_ctrl roundtrip: {core.parse_fixture_ctrl(srb)!r}")

if errors:
    for msg in errors:
        print(f"FAIL: {msg}", flush=True)
    sys.exit(1)

print(f"eg_version={core.EG_VERSION}", flush=True)
print(f"parser_build={core.FIXTURE_PARSER_BUILD}", flush=True)
print(f"fixture_core={core.__file__}", flush=True)
print("OK EG 2.2 BOM + TEMT DE + inject require_idle IPC", flush=True)
print("OK inject IPC (req_hdr=16 inject_done=39 forensics_hdr=40+8de)", flush=True)
print("OK fixture SRB eth ctrl frame", flush=True)
PY
