#pragma once
// Wi-Fi station manager, provisioning controller and USB provisioning service.
//
// The heavy policy lives in host-tested pure modules:
//   wifi_profiles.h   WiFiProfileStore (persistence + selection order)
//   wifi_selection.h  ProvisioningMode, backoff, SoftAP SSID/QR helpers
//
// This file is the ESP-IDF binding: it scans, connects known networks in
// selection order, serves the local Portal during an explicit provisioning
// mode, and parses the USB provisioning command protocol. It never starts the
// SoftAP on its own (docs/wifi-provisioning-plan.md section 3).

#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>

#include "esp_err.h"
#include "freertos/FreeRTOS.h"
#include "freertos/event_groups.h"
#include "wifi_profiles.h"
#include "wifi_selection.h"

#define WIFI_CONNECTED_BIT BIT0

// ---- Station lifecycle ----------------------------------------------------

// Boots the station: loads profiles (migrating the build-time SSID into a
// first-run profile when the store is empty), then tries known networks in
// selection order. Returns ESP_OK once Wi-Fi is initialised, even when no
// network is reachable; the device simply stays OFFLINE and retries.
esp_err_t wifi_manager_start(void);
EventGroupHandle_t wifi_manager_event_group(void);

// Current link state for the UI.
wearable::WifiLinkState wifi_manager_state(void);

// SSID of the network the station is associated with, or "" when offline.
const char *wifi_manager_current_ssid(void);

// ---- Settings > Network ---------------------------------------------------

size_t wifi_manager_profile_count(void);
// SSID for index [0, count). Never returns a password.
const char *wifi_manager_profile_ssid(size_t index);
// Which profile is currently connected, or -1.
int wifi_manager_current_profile_index(void);

// Forget one network (disconnects it and tries the remaining profiles) or all.
esp_err_t wifi_manager_forget(const char *ssid);
esp_err_t wifi_manager_forget_all(void);

// ---- Provisioning mode (manual, confirmed, explicit) ----------------------

// True while a pending approval blocks opening Wi-Fi Setup.
bool wifi_manager_setup_blocked(void);
// User-confirmed entry into provisioning. Starts the SoftAP + Portal.
esp_err_t wifi_manager_start_provisioning(void);
// Leave provisioning: stops the AP/Portal and returns to normal station mode.
void wifi_manager_stop_provisioning(void);
// Human Gate preemption. An incoming Approval owns the buttons, so it must also
// own the screen: cancel any in-flight candidate (its late result is ignored by
// generation), stop the SoftAP/Portal, and hand the display to the Approval.
// Returns true when provisioning was actually running and was stopped.
bool wifi_manager_preempt_for_approval(void);
wearable::ProvisioningMode wifi_manager_provisioning_mode(void);

// Provisioning screen values. All point at static storage; none contains a
// device or gateway credential.
const char *wifi_manager_provisioning_ssid(void);
const char *wifi_manager_provisioning_password(void);
const char *wifi_manager_provisioning_address(void);
// Standard Wi-Fi QR payload for the provisioning AP.
const char *wifi_manager_provisioning_qr(void);
// Last candidate outcome for the provisioning status line.
wearable::CandidateResult wifi_manager_last_candidate(void);
const char *wifi_manager_last_candidate_ssid(void);

// Candidate-first validation is driven by the Portal; it is exposed so the
// USB protocol and the Portal share one implementation.
esp_err_t wifi_manager_test_candidate(const char *ssid, const char *password);

// ---- USB provisioning command protocol ------------------------------------

// A versioned, framed, newline-delimited command/response protocol over the
// existing USB Serial/JTAG console. Passwords are accepted but never echoed.
//
// Request :  WFP/1 <verb> [args...]\n
// Response:  WFP/1 <status> <verb> [key=value...]\n
//            ... multi-line payload lines prefixed with "WFP/1 DATA "
//            WFP/1 END
//
// Verbs: status, list, add, remove, clear. `wifi_manager_handle_usb_line`
// consumes one complete line and writes the response through `reply`.
void wifi_manager_handle_usb_line(const char *line, char *reply, size_t reply_size);

// Bench/self-test hook: run a USB protocol exchange from host tests through a
// callback. Returns the number of response bytes written.
size_t wifi_manager_dispatch(const char *line, char *reply, size_t reply_size);

// True when an optional USB line contains a password field, so the caller can
// prove the response never echoes it.
bool wifi_usb_line_has_password(const char *line);