#ifndef NETWORK_ID_H
#define NETWORK_ID_H

// ============================================================================
// network_id.h — 802.11 frame-parser / network identification
//
// Replaces the RSSI-only sniffer with a management-frame parser that extracts
// BSSID, SSID, channel, and cipher info from beacon / probe-response frames.
// Non-management frames fall back to legacy RSSI-bin accounting via the
// internal legacy_rssi_observe() helper — existing rssi-per-channel stats are
// preserved.
//
// Integration:
//   1. Call network_id_init() from setup().
//   2. Replace:
//        esp_wifi_set_promiscuous_rx_cb(wifi_sniffer_cb);
//      with:
//        esp_wifi_set_promiscuous_rx_cb(network_id_sniffer_cb);
//   3. Call network_id_publish(sensor_id) every ~30 s (or on demand via
//      NETWORK_SCAN_DUMP command) to emit MSG_TYPE_NETWORK_LIST packets.
//
// Wire packet — MSG_TYPE_NETWORK_LIST = 0x15:
//   [0]       = 0x15
//   [1..4]    = sensor_id (LE uint32_t)
//   [5]       = entry count in this packet (1..4)
//   [6..]     = entries, each 16 bytes:
//                 [0..5]  bssid (6 bytes)
//                 [6..13] ssid_first8 (up to 8 bytes, zero-padded)
//                 [14]    channel (1..14)
//                 [15]    last_rssi (int8_t cast to uint8_t)
//
// Up to 4 entries per packet; multiple packets are emitted if count > 4.
// ============================================================================

#include <cstdint>
#include <cstddef>
#include <stdbool.h>

#ifdef ARDUINO
#  include "esp_wifi_types.h"
#else
#  ifndef WIFI_PROMISCUOUS_PKT_TYPE_T_DEFINED
#  define WIFI_PROMISCUOUS_PKT_TYPE_T_DEFINED
   typedef enum {
       NETWORK_ID_PKT_MGMT = 0,
       NETWORK_ID_PKT_CTRL = 1,
       NETWORK_ID_PKT_DATA = 2,
       NETWORK_ID_PKT_MISC = 3
   } wifi_promiscuous_pkt_type_t;
#  endif
#endif

// Maximum number of distinct networks tracked simultaneously (LRU eviction).
#define NETWORK_ID_TABLE_SIZE   32
// Maximum SSID storage length (includes null terminator).
#define NETWORK_ID_SSID_MAX     33
// Entries per MSG_TYPE_NETWORK_LIST packet.
#define NETWORK_ID_ENTRIES_PER_PKT  4
// Bytes per serialized entry in a NETWORK_LIST packet.
#define NETWORK_ID_ENTRY_BYTES   16
// Publish interval in milliseconds.
#define NETWORK_ID_PUBLISH_INTERVAL_MS  30000

// Cipher identifiers stored in NetworkEntry.cipher_id
#define CIPHER_UNKNOWN  0x00
#define CIPHER_WEP      0x01
#define CIPHER_TKIP     0x02
#define CIPHER_CCMP     0x04   // WPA2/3 AES
#define CIPHER_OPEN     0x08

// MSG type constant (mirrors config.h naming convention; defined here so
// network_id.h can be included before config.h if needed — the build guards
// against double-definition).
#ifndef MSG_TYPE_NETWORK_LIST
#define MSG_TYPE_NETWORK_LIST   0x15u
#endif
#ifndef MSG_TYPE_PAYLOAD_CHUNK
#define MSG_TYPE_PAYLOAD_CHUNK  0x14u
#endif
#ifndef MSG_TYPE_AUTH_TOKEN
#define MSG_TYPE_AUTH_TOKEN     0x1Du
#endif

// ---- Network table entry ----
struct NetworkEntry {
    uint8_t  bssid[6];
    char     ssid[NETWORK_ID_SSID_MAX];  // null-terminated, up to 32 chars
    uint8_t  channel;
    int8_t   last_rssi;
    uint8_t  cipher_id;     // CIPHER_* bitmask
    uint32_t last_seen_ms;  // millis() timestamp of last observation
};

// ---------------------------------------------------------------------------
// Initialise internal table and state. Must be called before the promiscuous
// callback is registered.
// ---------------------------------------------------------------------------
void network_id_init();

// ---------------------------------------------------------------------------
// Promiscuous RX callback — register with:
//   esp_wifi_set_promiscuous_rx_cb(network_id_sniffer_cb);
//
// For mgmt/beacon and probe-response frames: parses BSSID, SSID, channel,
// cipher and upserts into the network table (LRU eviction when full).
// For all other frame types: delegates to legacy_rssi_observe() to maintain
// existing per-channel RSSI accounting without disruption.
// ---------------------------------------------------------------------------
void network_id_sniffer_cb(void* buf, wifi_promiscuous_pkt_type_t type);

// ---------------------------------------------------------------------------
// Return the number of entries currently in the network table (0..32).
// ---------------------------------------------------------------------------
int network_id_count();

// ---------------------------------------------------------------------------
// Retrieve the entry at logical index idx (0-based, sorted by last_seen_ms
// descending). Returns false if idx >= network_id_count().
// ---------------------------------------------------------------------------
bool network_id_get(int idx, NetworkEntry* out);

// ---------------------------------------------------------------------------
// Emit one or more MSG_TYPE_NETWORK_LIST packets (via mesh_publish_raw) for
// the current table snapshot. Each packet carries up to 4 entries.
// Returns true if at least one packet was successfully published.
// ---------------------------------------------------------------------------
bool network_id_publish(uint32_t sensor_id);

#endif // NETWORK_ID_H
