#pragma once

/**
 * @file bluetooth_provisioning.h
 * @brief 蓝牙配网模块头文件（基于自定义 GATT Server）
 *
 * 使用自定义 BLE GATT Server 实现配网通讯，
 * 采用原始广播数据（raw advertising）确保手机系统蓝牙可发现。
 * 保留完整的 WiFi 配网业务逻辑、状态机和事件回调。
 */

#include <functional>
#include <string>

// 使用条件编译避免IDE环境中的头文件错误
#ifdef ESP_PLATFORM
#include "esp_gap_ble_api.h"
#include "esp_gatts_api.h"
#include "esp_gatt_common_api.h"
#include "esp_wifi.h"
#include "esp_event.h"
#else
// 在非ESP环境中定义必要的类型和常量
typedef int esp_event_base_t;
typedef void* wifi_ap_record_t;
#endif

// ============================================================
// 配网协议命令定义 (手机 → 设备, WRITE 特征)
// ============================================================
#define PROV_CMD_SET_SSID           0x01  // 设置 WiFi SSID
#define PROV_CMD_SET_PASSWORD       0x02  // 设置 WiFi 密码
#define PROV_CMD_SET_BSSID          0x03  // 设置 BSSID (6字节)
#define PROV_CMD_CONNECT_AP         0x04  // 请求连接 WiFi
#define PROV_CMD_DISCONNECT_AP      0x05  // 请求断开 WiFi
#define PROV_CMD_GET_WIFI_LIST      0x06  // 请求 WiFi 列表
#define PROV_CMD_DISCONNECT_BLE     0x07  // 请求断开 BLE
#define PROV_CMD_SET_WIFI_MODE      0x08  // 设置 WiFi 模式
#define PROV_CMD_GET_WIFI_STATUS    0x09  // 获取 WiFi 状态
#define PROV_CMD_CUSTOM_DATA        0x10  // 自定义数据

// ============================================================
// 配网协议响应定义 (设备 → 手机, NOTIFY 特征)
// ============================================================
#define PROV_RESP_WIFI_STATUS       0x81  // WiFi 状态: [success(1)][reason(1)]
#define PROV_RESP_WIFI_LIST         0x82  // WiFi 列表: [rssi(1)][ssid_len(1)][ssid...]
#define PROV_RESP_WIFI_LIST_END     0x83  // WiFi 列表结束标记
#define PROV_RESP_CUSTOM_DATA       0x84  // 自定义数据

// ============================================================
// GATT 服务配置
// ============================================================
#define PROV_SERVICE_UUID           0xABF0  // 配网服务 UUID
#define PROV_CHAR_WRITE_UUID        0xABF1  // 写入特征 UUID (手机→设备)
#define PROV_CHAR_NOTIFY_UUID       0xABF2  // 通知特征 UUID (设备→手机)
#define PROV_APP_ID                 2       // GATTS App ID
#define PROV_HANDLE_NUM             8       // Service handle 数量
#define PROV_LOCAL_MTU              512     // 本地 MTU

/**
 * @brief 蓝牙配网状态枚举
 */
enum class BluetoothProvisioningState {
    IDLE,           //< 空闲状态，未启动配网
    INITIALIZING,   //< 初始化中，正在初始化蓝牙和服务
    ADVERTISING,    //< 广播中，等待手机客户端连接
    CONNECTED,      //< 已连接，手机客户端已连接到设备
    PROVISIONING,   //< 配网中，正在接收和处理WiFi凭据
    SUCCESS,        //< 配网成功，WiFi连接建立成功
    FAILED,         //< 配网失败，WiFi连接失败或其他错误
    STOPPED         //< 已停止，配网服务已停止
};

/**
 * @brief 蓝牙配网事件类型
 */
enum class BluetoothProvisioningEvent {
    STATE_CHANGED,      //< 状态改变事件
    WIFI_CREDENTIALS,   //< 收到WiFi凭据事件
    WIFI_CONNECTED,     //< WiFi连接成功事件
    WIFI_FAILED,        //< WiFi连接失败事件
    CLIENT_CONNECTED,   //< 客户端连接事件
    CLIENT_DISCONNECTED //< 客户端断开事件
};

/**
 * @brief WiFi凭据结构体
 */
struct WiFiCredentials {
    std::string ssid;       //< WiFi网络名称（SSID）
    std::string password;   //< WiFi网络密码
    uint8_t bssid[6];      //< WiFi接入点的MAC地址（BSSID）
    bool bssid_set;        //< 是否设置了BSSID
};

/**
 * @brief 蓝牙配网事件回调函数类型
 */
using BluetoothProvisioningCallback = std::function<void(BluetoothProvisioningEvent event, void* data)>;

/**
 * @brief 蓝牙配网封装类（基于自定义 GATT Server）
 *
 * 使用自定义 BLE GATT Server + 原始广播数据，
 * 手机系统蓝牙可直接搜索到设备。保留完整的 WiFi 配网业务逻辑。
 */
class BluetoothProvisioning {
public:
    BluetoothProvisioning();
    ~BluetoothProvisioning();

    bool Initialize();
    bool Deinitialize();
    bool StartProvisioning();
    bool StopProvisioning();

    BluetoothProvisioningState GetState() const { return state_; }
    void SetCallback(BluetoothProvisioningCallback callback) { callback_ = callback; }
    const WiFiCredentials& GetWiFiCredentials() const { return wifi_credentials_; }
    bool IsClientConnected() const { return client_connected_; }
    std::string GetStateString() const;

    void ReportWiFiStatus(bool success, uint8_t reason = 0);
    void SendWiFiList(const wifi_ap_record_t* ap_list, uint16_t ap_count);
    bool SendMacAddressReliably();
    void ResetMacSendingState();

private:
    BluetoothProvisioningState state_;
    BluetoothProvisioningCallback callback_;
    WiFiCredentials wifi_credentials_;
    bool client_connected_;
    bool initialized_;
    bool delayed_disconnect_;
    bool wifi_connecting_;
    bool mac_address_sent_;

    static BluetoothProvisioning* instance_;

    void SetState(BluetoothProvisioningState new_state);
    void TriggerCallback(BluetoothProvisioningEvent event, void* data = nullptr);

#ifdef ESP_PLATFORM
    // GATT 相关成员
    esp_gatt_if_t gatts_if_ = ESP_GATT_IF_NONE;
    uint16_t service_handle_ = 0;
    uint16_t write_char_handle_ = 0;
    uint16_t notify_char_handle_ = 0;
    uint16_t notify_cccd_handle_ = 0;
    uint16_t conn_id_ = 0;
    bool notify_enabled_ = false;
    uint16_t mtu_ = 23;

    // BLE 回调
    static void GattsEventHandler(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t* param);
    static void GapEventHandler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t* param);
    void HandleGattsEvent(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t* param);

    // GATT 辅助方法
    void CreateService(esp_gatt_if_t gatts_if);
    void StartAdvertising();
    bool SendNotify(const uint8_t* data, uint16_t len);
    void ProcessWriteData(const uint8_t* data, uint16_t len);

    // WiFi 事件处理
    static void WiFiEventHandler(void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data);
    static void IPEventHandler(void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data);
#endif

    BluetoothProvisioning(const BluetoothProvisioning&) = delete;
    BluetoothProvisioning& operator=(const BluetoothProvisioning&) = delete;
};
