#ifndef MESH_TIMESYNC_H
#define MESH_TIMESYNC_H

// ============================================================================
// mesh_timesync.h — Wall-clock sync via T2 leader broadcast
//
// The T1 sensor has no GPS. The T2 gateway emits MSG_TYPE_TIME_SYNC (0x19)
// every 30 s. This module receives those packets, computes a clock offset
// relative to millis(), and tracks it with a single-pole IIR (alpha=0.2).
//
// Packet format (12 bytes):
//   [0]       = 0x19  (MSG_TYPE_TIME_SYNC)
//   [1..8]    = epoch_us (uint64_t, little-endian)
//   [9..11]   = reserved
//
// The module is marked synced after 3 successful packets. Until then
// timesync_is_synced() returns false and timesync_now_utc_ms() falls back
// to 0.
// ============================================================================

#include <cstdint>
#include <cstddef>

// Minimum successful packets before is_synced() returns true.
#define TIMESYNC_MIN_PACKETS  3

// IIR smoothing alpha (0.0 = never update, 1.0 = no smoothing)
#define TIMESYNC_IIR_ALPHA    0.2f

// Initialise module — must be called once before any other function.
void timesync_init();

// Feed a raw mesh packet. If buf[0] == MSG_TYPE_TIME_SYNC and len >= 9,
// the offset is extracted and the IIR is updated.
void timesync_handle_packet(const uint8_t* buf, size_t len);

// Return the current best-estimate UTC epoch in milliseconds.
// Returns 0 if not yet synced (timesync_is_synced() == false).
uint64_t timesync_now_utc_ms();

// True after TIMESYNC_MIN_PACKETS successful packets have been processed.
bool timesync_is_synced();

// ---------------------------------------------------------------------------
// Resolve the UTC timestamp to publish for ONE outbound report.
//
// SINGLE SOURCE OF TRUTH for time, mirroring location_resolve_report() for
// position. This logic previously lived only inside c2_wifi_bridge.cpp
// (resolve_detection_ts), so the SAME detection went to C2 with real UTC and
// to MQTT with boot-seconds — measured live: C2 ts=1785668807 vs MQTT ts=109.
//
// Order: the event's own value if it already looks like a real epoch (covers a
// peer's already-stamped relayed event) -> mesh/NTP timesync -> GPS UTC ->
// the raw value as a last resort.
// ---------------------------------------------------------------------------
uint32_t timesync_resolve_report_ts(uint32_t evt_timestamp_utc);

// Below this, a value is boot-seconds rather than a real epoch. Matches the
// threshold the C2 path has always used.
#define TIMESYNC_PLAUSIBLE_EPOCH  1600000000u

#endif // MESH_TIMESYNC_H
