#ifndef C2_WIFI_BRIDGE_H
#define C2_WIFI_BRIDGE_H

// ============================================================================
// c2_wifi_bridge.h — Direct WiFi POST of promoted detections to OpenForge C2
// (ADDITIVE, off by default).
//
// Today a promoted (FFPS-corroborated) detection reaches OpenForge C2 only
// via BLE notify -> a phone bridge app relaying it onward. When this sensor
// itself holds a WiFi connection (see wifi_status_server.h), it can also
// POST the same detection JSON directly over its own 2.4 GHz WiFi, with no
// phone required. Reuses ble_companion.cpp's build_detection_json() so both
// paths carry byte-identical fields.
//
// Join via the existing WIFI_CONNECT serial console command, then configure
// the C2 endpoint with:
//   C2_WIFI_CONNECT <host> <port> <path>
// e.g.  C2_WIFI_CONNECT pdlopenforge.com 443 /api/sensor/detection
// ============================================================================

#include <cstdint>
#include "config.h"

void c2_wifi_bridge_init();
void c2_wifi_bridge_connect(const char* host, uint16_t port, const char* path);

// Loads a config previously saved by c2_wifi_bridge_connect() (persisted to
// NVS) and reconnects automatically if one exists. Call once from setup(),
// after c2_wifi_bridge_init(). No-op (and does not mark the bridge
// configured) if nothing was ever persisted.
void c2_wifi_bridge_restore_from_nvs();

// ---------------------------------------------------------------------------
// Heartbeat health observability.
//
// Added because a wedged C2 heartbeat was INVISIBLE from the device: the unit
// answered HTTP, published MQTT and relayed LoRa while its C2 health post had
// been dead for ~an hour. Surfacing these in /status means the condition can
// be seen remotely instead of inferred from C2 going quiet.
// ---------------------------------------------------------------------------
// Seconds since the last SUCCESSFUL health post, or UINT32_MAX if none has
// ever succeeded since boot. The sentinel matters: an earlier version returned
// 0 for both cases, and a unit that had never reached C2 looked identical to
// one that had just checked in.
uint32_t c2_wifi_bridge_seconds_since_success();
// (c2_wifi_bridge_is_configured() already exists further down — a unit with no
// endpoint configured reports healthy on every other axis while being entirely
// absent from C2, so /status surfaces it.)
uint32_t c2_wifi_bridge_consecutive_failures();
uint32_t c2_wifi_bridge_stall_recoveries();

// Posts a promoted DetectionEvent if WiFi + endpoint are both configured.
// No-op (returns false) otherwise — the LoRa/BLE paths are unaffected either
// way, this is a pure add-on delivery path.
bool c2_wifi_bridge_post_detection(const DetectionEvent& evt);

// Posts a DetectionEvent received from a PEER sensor over LoRa — this unit
// acting as a WiFi-connected relay for a sensor with no WiFi/T2 gateway of
// its own. Unlike c2_wifi_bridge_post_detection() (which always reports
// THIS device's own SENSOR_NAME), this uses the peer's actual sensor_id
// from the LoRa packet, and tags gateway_id as "LORA_RELAY:<this device>"
// so C2 can tell a relayed report apart from a direct WiFi POST.
bool c2_wifi_bridge_post_relayed_detection(const DetectionEvent& evt);

// POST /api/sensor/health (same host:port as the detection path, fixed
// suffix) with this sensor's own position, so it shows up on the C2 map's
// sensor layer even when it has never detected anything. Without this,
// nothing ever tells C2 where the sensor itself is -- a detection-only
// bridge has no path for "I exist, here's my position" at all.
bool c2_wifi_bridge_post_health();

// Posts a HEALTH packet received from a PEER sensor over LoRa -- the same
// relay role as c2_wifi_bridge_post_relayed_detection(), but for health
// packets (DetectionEvent with msg_type == MSG_TYPE_HEALTH, fields
// repurposed per health_report.cpp: battery_pct/rssi/lat_fixed/lon_fixed
// are real, class_label/signature_hash are not). gateway_id is tagged
// "LORA_RELAY:<this device>" like the detection relay path.
bool c2_wifi_bridge_post_relayed_health(const DetectionEvent& evt);

// Drives the periodic health heartbeat (C2_WIFI_HEALTH_INTERVAL_MS) — call
// every loop() cycle alongside c2_wifi_bridge's other tick-driven pieces.
// No-op until c2_wifi_bridge_connect() has been called and WiFi is up.
void c2_wifi_bridge_tick();

struct C2WifiBridgeStats {
    bool     configured;
    uint32_t posts_ok;
    uint32_t posts_failed;
    uint32_t health_posts_ok;
    uint32_t health_posts_failed;
};

void c2_wifi_bridge_get_stats(C2WifiBridgeStats* out);

// Accessors so other modules (wifi_command_poll.cpp) can reuse the same
// C2 connection c2_wifi_bridge_connect() configured, without a second
// connect step or duplicated host/port state.
const char* c2_wifi_bridge_host();
uint16_t    c2_wifi_bridge_port();
bool        c2_wifi_bridge_is_configured();

#endif // C2_WIFI_BRIDGE_H
