#ifndef AUTH_GATE_H
#define AUTH_GATE_H

// ============================================================================
// auth_gate.h — Ed25519 auth-token verification gate
//
// Every DELIVER_PAYLOAD command MUST pass through authgate_verify() before
// any injection is attempted.  Without a valid, non-expired C2-signed token
// the delivery path is hard-blocked — all wifi_inject_send() calls must be
// gated by this module.
//
// Token wire format (84 bytes total):
//   [0..3]    sensor_id    (LE uint32_t)
//   [4..9]    target_bssid (6 bytes)
//   [10..13]  payload_id   (LE uint32_t)
//   [14..21]  expiry_ms    (LE uint64_t, milliseconds since epoch / boot epoch)
//   [22..23]  reserved     (2 bytes, must be zero — not verified, silently ignored)
//   [24..87]  sig64        (Ed25519 signature over bytes [0..23], 64 bytes)
//
// The signature covers the first 24 bytes of the token (sensor_id | bssid |
// payload_id | expiry_ms | reserved).
//
// Public key source:
//   The NVS-stored Ed25519 public key written by Batch B's
//   ota_signed_set_pubkey() (namespace "pdl_pki", key "ed25519_pk").
//   authgate_verify() calls ota_signed_get_pubkey() lazily on first use and
//   caches the key for the session.  If ota_signed.cpp is not yet linked,
//   the extern declaration is resolved by the Batch B integrator.
//
// Audit log:
//   A ring buffer of the last 32 delivery attempts is kept in NVS
//   (namespace "pdl_audit", key "gate_log").  Each record is 32 bytes:
//     [0..7]   ts_ms (LE uint64_t)
//     [8..11]  sensor_id (LE uint32_t)
//     [12..17] bssid (6 bytes)
//     [18..21] payload_id (LE uint32_t)
//     [22]     result (0=pass, 1=fail_expired, 2=fail_sig, 3=fail_id, 4=fail_nopk)
//     [23..30] token_hash_first8 (first 8 bytes of SHA-256 of raw token)
//     [31]     reserved
//
//   Use authgate_audit_dump() to retrieve the log as a contiguous byte
//   stream (up to 32 * 32 = 1024 bytes).
// ============================================================================

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

// Token layout constants
#define AUTHGATE_TOKEN_LEN      84   // total wire bytes
#define AUTHGATE_TOKEN_MSG_LEN  24   // signed portion (bytes 0..23)
#define AUTHGATE_SIG_OFFSET     24   // offset of the 64-byte signature

// Audit log constants
#define AUTHGATE_AUDIT_RING_SIZE   32   // entries in ring buffer
#define AUTHGATE_AUDIT_ENTRY_BYTES 32   // bytes per entry
#define AUTHGATE_AUDIT_MAX_DUMP    (AUTHGATE_AUDIT_RING_SIZE * AUTHGATE_AUDIT_ENTRY_BYTES)

// Audit result codes
#define AUDIT_RESULT_PASS        0
#define AUDIT_RESULT_FAIL_EXPIRY 1
#define AUDIT_RESULT_FAIL_SIG    2
#define AUDIT_RESULT_FAIL_ID     3
#define AUDIT_RESULT_FAIL_NOPK   4

// NVS namespace / key for the audit ring
#define AUTH_AUDIT_NVS_NS   "pdl_audit"
#define AUTH_AUDIT_NVS_KEY  "gate_log"

// ---------------------------------------------------------------------------
// Core verification function.
//
// Parameters:
//   sensor_id   — this sensor's enrolled ID (from enrollment_get_sensor_id())
//   bssid       — the target BSSID from the DELIVER_PAYLOAD command params
//   payload_id  — the payload_id from the command params
//   now_ms      — current time in ms (millis() on device; test-injectable)
//   token       — pointer to the 84-byte auth token
//   token_len   — must be exactly AUTHGATE_TOKEN_LEN (84)
//
// Returns true ONLY if ALL of the following hold:
//   (a) token_len == AUTHGATE_TOKEN_LEN
//   (b) token[0..3] (sensor_id_le) == sensor_id parameter
//   (c) token[4..9] (target_bssid) matches bssid parameter
//   (d) token[10..13] (payload_id_le) == payload_id parameter
//   (e) expiry_ms (token[14..21]) > now_ms (token not expired)
//   (f) Ed25519 signature (token[24..87]) over token[0..23] verifies against
//       the NVS-stored public key (loaded via ota_signed_get_pubkey)
//
// Any failure causes an audit log entry and returns false.
// ---------------------------------------------------------------------------
bool authgate_verify(uint32_t         sensor_id,
                     const uint8_t    bssid[6],
                     uint32_t         payload_id,
                     uint64_t         now_ms,
                     const uint8_t*   token,
                     size_t           token_len);

// ---------------------------------------------------------------------------
// Audit log API
// ---------------------------------------------------------------------------

// Append one entry to the NVS ring buffer.  Called internally by
// authgate_verify(); exposed for testing and for callers that want to log
// cancellation events.
void authgate_audit_append(uint64_t       ts_ms,
                           uint32_t       sensor_id,
                           const uint8_t  bssid[6],
                           uint32_t       payload_id,
                           uint8_t        result,
                           const uint8_t* token,
                           size_t         token_len);

// Serialize the audit ring to out_buf (max max_len bytes).
// Returns number of bytes written (multiple of AUTHGATE_AUDIT_ENTRY_BYTES).
int authgate_audit_dump(uint8_t* out_buf, size_t max_len);

// ---------------------------------------------------------------------------
// Key cache management (normally internal; exposed for tests)
// ---------------------------------------------------------------------------

// Force a reload of the Ed25519 public key from NVS into the module cache.
// Useful after ota_signed_set_pubkey() is called during a session.
void authgate_reload_pubkey();

#endif // AUTH_GATE_H
