///|
/// F1 lockwire live-capability completion surface.
///
/// Enumerates the six native capabilities that previously blocked the
/// PROFINET/EtherCAT rawnet → lockwire session bindings: local_mac discovery,
/// last_rx receive timestamp, non-blocking wrapper, monotonic_millis,
/// sleep_until_micros, and Windows realtime thread affinity. Each capability
/// ships a native C ABI (Windows/Linux platform-gated) and a wasm-gc fallback
/// that returns not-implemented, so `moon test` on wasm-gc proves the catalog
/// and policy shape while real live I/O stays gated by Blocked hardware tasks.

///|
pub(all) struct NativeLiveCapability {
  id : String
  capability_family : String
  native_symbol : String
  fallback_returns_not_implemented : Bool
  implemented_probe_symbol : String
  platform_scope : String
  unblocks_binding : String
} derive(Eq, Debug)

///|
pub(all) struct NativeLiveCapabilityReport {
  capability_count : Int
  clock_capability_count : Int
  rt_affinity_capability_count : Int
  npcap_live_ext_capability_count : Int
  raw_socket_live_ext_capability_count : Int
  local_mac_capability_count : Int
  last_capture_capability_count : Int
  nonblock_capability_count : Int
  all_fallbacks_return_not_implemented : Bool
  all_implemented_probes_present : Bool
  live_evidence_present : Bool
  evidence_label : String
} derive(Eq, Debug)

///|
pub fn native_live_capability_catalog() -> Array[NativeLiveCapability] {
  [
    {
      id: "native.live-capability.monotonic-millis",
      capability_family: "clock-millis",
      native_symbol: "lockwire_native_monotonic_millis",
      fallback_returns_not_implemented: true,
      implemented_probe_symbol: "ffi_monotonic_millis",
      platform_scope: "windows+linux+unsupported-fallback",
      unblocks_binding: "profinet.rawnet.clock.to_lockwire_highres_clock",
    },
    {
      id: "native.live-capability.sleep-until-micros",
      capability_family: "clock-sleep",
      native_symbol: "lockwire_native_sleep_until_micros",
      fallback_returns_not_implemented: true,
      implemented_probe_symbol: "ffi_sleep_until_micros",
      platform_scope: "windows+linux+unsupported-fallback",
      unblocks_binding: "profinet.rawnet.clock.to_lockwire_highres_clock",
    },
    {
      id: "native.live-capability.win-rt-affinity",
      capability_family: "rt-affinity",
      native_symbol: "lockwire_native_win_rt_set_affinity",
      fallback_returns_not_implemented: true,
      implemented_probe_symbol: "ffi_win_rt_supported",
      platform_scope: "windows+unsupported-fallback",
      unblocks_binding: "profinet.rawnet.clock.to_lockwire_highres_clock",
    },
    {
      id: "native.live-capability.npcap-local-mac",
      capability_family: "npcap-local-mac",
      native_symbol: "lockwire_native_npcap_local_mac",
      fallback_returns_not_implemented: true,
      implemented_probe_symbol: "ffi_npcap_local_mac",
      platform_scope: "windows+unsupported-fallback",
      unblocks_binding: "profinet.rawnet.windows_npcap.to_lockwire_session",
    },
    {
      id: "native.live-capability.npcap-last-capture-micros",
      capability_family: "npcap-last-capture",
      native_symbol: "lockwire_native_npcap_last_capture_micros",
      fallback_returns_not_implemented: true,
      implemented_probe_symbol: "ffi_npcap_last_capture_micros",
      platform_scope: "windows+unsupported-fallback",
      unblocks_binding: "profinet.rawnet.windows_npcap.to_lockwire_session",
    },
    {
      id: "native.live-capability.npcap-set-nonblock",
      capability_family: "npcap-nonblock",
      native_symbol: "lockwire_native_npcap_set_nonblock",
      fallback_returns_not_implemented: true,
      implemented_probe_symbol: "ffi_npcap_set_nonblock",
      platform_scope: "windows+unsupported-fallback",
      unblocks_binding: "profinet.rawnet.windows_npcap.to_lockwire_session",
    },
    {
      id: "native.live-capability.raw-socket-local-mac",
      capability_family: "raw-socket-local-mac",
      native_symbol: "lockwire_native_raw_socket_local_mac",
      fallback_returns_not_implemented: true,
      implemented_probe_symbol: "ffi_raw_socket_local_mac",
      platform_scope: "linux+unsupported-fallback",
      unblocks_binding: "profinet.rawnet.linux_af_packet.to_lockwire_session",
    },
    {
      id: "native.live-capability.raw-socket-last-capture-micros",
      capability_family: "raw-socket-last-capture",
      native_symbol: "lockwire_native_raw_socket_last_capture_micros",
      fallback_returns_not_implemented: true,
      implemented_probe_symbol: "ffi_raw_socket_last_capture_micros",
      platform_scope: "linux+unsupported-fallback",
      unblocks_binding: "profinet.rawnet.linux_af_packet.to_lockwire_session",
    },
    {
      id: "native.live-capability.raw-socket-set-nonblock",
      capability_family: "raw-socket-nonblock",
      native_symbol: "lockwire_native_raw_socket_set_nonblock",
      fallback_returns_not_implemented: true,
      implemented_probe_symbol: "ffi_raw_socket_set_nonblock",
      platform_scope: "linux+unsupported-fallback",
      unblocks_binding: "profinet.rawnet.linux_af_packet.to_lockwire_session",
    },
  ]
}

///|
pub fn NativeLiveCapabilityReport::passes(
  self : NativeLiveCapabilityReport,
) -> Bool {
  self.capability_count == 9 &&
  self.clock_capability_count == 2 &&
  self.rt_affinity_capability_count == 1 &&
  self.npcap_live_ext_capability_count == 3 &&
  self.raw_socket_live_ext_capability_count == 3 &&
  self.local_mac_capability_count == 2 &&
  self.last_capture_capability_count == 2 &&
  self.nonblock_capability_count == 2 &&
  self.all_fallbacks_return_not_implemented &&
  self.all_implemented_probes_present &&
  !self.live_evidence_present &&
  self.evidence_label == "native.live-capability.report"
}

///|
pub fn native_live_capability_report() -> NativeLiveCapabilityReport {
  let catalog = native_live_capability_catalog()
  let count = fn(fam : String) {
    let mut n = 0
    for entry in catalog {
      if entry.capability_family == fam {
        n += 1
      }
    }
    n
  }
  let contains_family = fn(fam : String) -> Bool {
    for entry in catalog {
      if entry.capability_family == fam {
        return true
      }
    }
    false
  }
  {
    capability_count: catalog.length(),
    clock_capability_count: count("clock-millis") + count("clock-sleep"),
    rt_affinity_capability_count: count("rt-affinity"),
    npcap_live_ext_capability_count: count("npcap-local-mac") +
    count("npcap-last-capture") +
    count("npcap-nonblock"),
    raw_socket_live_ext_capability_count: count("raw-socket-local-mac") +
    count("raw-socket-last-capture") +
    count("raw-socket-nonblock"),
    local_mac_capability_count: count("npcap-local-mac") +
    count("raw-socket-local-mac"),
    last_capture_capability_count: count("npcap-last-capture") +
    count("raw-socket-last-capture"),
    nonblock_capability_count: count("npcap-nonblock") +
    count("raw-socket-nonblock"),
    all_fallbacks_return_not_implemented: catalog.all(fn(entry) {
      entry.fallback_returns_not_implemented
    }),
    all_implemented_probes_present: contains_family("clock-millis") &&
    contains_family("clock-sleep") &&
    contains_family("rt-affinity") &&
    contains_family("npcap-local-mac") &&
    contains_family("npcap-last-capture") &&
    contains_family("npcap-nonblock") &&
    contains_family("raw-socket-local-mac") &&
    contains_family("raw-socket-last-capture") &&
    contains_family("raw-socket-nonblock"),
    live_evidence_present: false,
    evidence_label: "native.live-capability.report",
  }
}

///|
pub fn monotonic_millis() -> Int64 {
  ffi_monotonic_millis()
}

///|
pub fn sleep_until_micros(deadline_micros : Int64) -> Int {
  ffi_sleep_until_micros(deadline_micros)
}

///|
pub fn win_rt_set_affinity(mask : UInt, priority : Int) -> Int {
  ffi_win_rt_set_affinity(mask, priority)
}

///|
pub fn win_rt_supported() -> Int {
  ffi_win_rt_supported()
}

///|
pub fn native_npcap_local_mac(interface_name : String) -> Bytes {
  ffi_npcap_local_mac(@utf8.encode(interface_name))
}

///|
pub fn native_npcap_last_capture_micros() -> Int64 {
  ffi_npcap_last_capture_micros()
}

///|
pub fn NativeNpcapLiveAdapter::local_mac(
  self : NativeNpcapLiveAdapter,
) -> Bytes {
  ffi_npcap_local_mac(@utf8.encode(self.interface_name))
}

///|
pub fn NativeNpcapLiveAdapter::last_capture_micros(
  self : NativeNpcapLiveAdapter,
) -> Int64 {
  ignore(self)
  ffi_npcap_last_capture_micros()
}

///|
pub fn NativeNpcapLiveAdapter::set_nonblock(
  self : NativeNpcapLiveAdapter,
  enable : Bool,
) -> Int {
  ffi_npcap_set_nonblock(self.fd, if enable { 1 } else { 0 })
}

///|
pub fn NativeNpcapLiveAdapter::try_capture(
  self : NativeNpcapLiveAdapter,
) -> Bytes raise NativeLinkError {
  let frame = ffi_npcap_capture_one(self.fd, 0)
  if frame.is_empty() && native_last_error_code() < 0 {
    raise native_link_error("npcap_try_capture")
  }
  frame
}

///|
pub fn native_raw_socket_local_mac(interface_name : String) -> Bytes {
  ffi_raw_socket_local_mac(@utf8.encode(interface_name))
}

///|
pub fn native_raw_socket_last_capture_micros() -> Int64 {
  ffi_raw_socket_last_capture_micros()
}

///|
pub fn NativeRawSocketAdapter::local_mac(
  self : NativeRawSocketAdapter,
) -> Bytes {
  ffi_raw_socket_local_mac(@utf8.encode(self.interface_name))
}

///|
pub fn NativeRawSocketAdapter::last_capture_micros(
  self : NativeRawSocketAdapter,
) -> Int64 {
  ignore(self)
  ffi_raw_socket_last_capture_micros()
}

///|
pub fn NativeRawSocketAdapter::set_nonblock(
  self : NativeRawSocketAdapter,
  enable : Bool,
) -> Int {
  ffi_raw_socket_set_nonblock(self.fd, if enable { 1 } else { 0 })
}

///|
pub fn NativeRawSocketAdapter::try_capture(
  self : NativeRawSocketAdapter,
) -> Bytes raise NativeLinkError {
  let frame = ffi_raw_socket_capture_one(self.fd, 0)
  if frame.is_empty() && native_last_error_code() < 0 {
    raise native_link_error("raw_socket_try_capture")
  }
  frame
}