#pragma once

/**
 * @file bluetooth_provisioning.h
 * @brief BluFi蓝牙配网模块头文件
 * 
 * 本文件定义了BluFi蓝牙配网的相关接口，包括配网状态管理、
 * 事件处理、WiFi凭据传输等功能。提供简单易用的C++接口
 * 封装ESP-IDF的BLUFI功能，用于通过蓝牙进行WiFi配网操作。
 */

#include <functional>
#include <string>

// 蓝牙设备名称 广播名称 宏定义，自动引用SDK配置，可打开SDK修改蓝牙名称
#define BLU_NAME CONFIG_BLUETOOTH_PROVISIONING_DEVICE_NAME

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

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

/**
 * @brief 蓝牙配网事件类型
 * 
 * 定义配网过程中可能发生的各种事件，用于事件回调和状态通知
 */
enum class BluetoothProvisioningEvent {
    STATE_CHANGED,      //< 状态改变事件，配网状态发生变化
    WIFI_CREDENTIALS,   //< 收到WiFi凭据事件，从手机接收到WiFi信息
    WIFI_CONNECTED,     //< WiFi连接成功事件，设备成功连接到WiFi网络
    WIFI_FAILED,        //< WiFi连接失败事件，设备连接WiFi失败
    CLIENT_CONNECTED,   //< 客户端连接事件，手机客户端连接到设备
    CLIENT_DISCONNECTED //< 客户端断开事件，手机客户端断开连接
};

/**
 * @brief WiFi凭据结构体
 * 
 * 存储从手机客户端接收到的WiFi连接信息
 */
struct WiFiCredentials {
    std::string ssid;       //< WiFi网络名称（SSID）
    std::string password;   //< WiFi网络密码
    uint8_t bssid[6];      //< WiFi接入点的MAC地址（BSSID），可选
    bool bssid_set;        //< 是否设置了BSSID，用于指定特定的接入点
};

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

/**
 * @brief 蓝牙配网封装类
 * 
 * 该类封装了ESP-IDF的BLUFI功能，提供简单易用的C++接口
 * 用于通过蓝牙进行WiFi配网操作。支持状态管理、事件回调、WiFi凭据接收等功能。
 * 
 * 典型使用流程：
 * 1. 创建BluetoothProvisioning实例
 * 2. 设置事件回调函数
 * 3. 调用StartProvisioning()开始配网
 * 4. 处理回调事件
 * 5. 配网完成后调用StopProvisioning()
 */
class BluetoothProvisioning {
public:
    /**
     * @brief 构造函数
     * 
     * 初始化蓝牙配网对象，设置默认参数和状态
     */
    BluetoothProvisioning();
    
    /**
     * @brief 析构函数
     * 
     * 清理资源，停止配网服务，释放蓝牙相关资源
     */
    ~BluetoothProvisioning();

    /**
     * @brief 初始化蓝牙配网功能
     * 
     * 初始化蓝牙控制器、蓝牙栈和BluFi服务，为配网做准备
     * 
     * @return true 初始化成功，false 初始化失败
     */
    bool Initialize();

    /**
     * @brief 反初始化蓝牙配网功能
     * 
     * 清理蓝牙资源，释放内存，恢复系统状态
     * 
     * @return true 反初始化成功，false 反初始化失败
     */
    bool Deinitialize();

    /**
     * @brief 开始蓝牙配网
     * 
     * 启动BluFi服务，开始广播等待手机客户端连接
     * 
     * @param device_name 蓝牙设备名称（可选，默认为"BLUFI_Airhub"），手机端会看到此名称
     * @return true 启动成功，false 启动失败
     */
    bool StartProvisioning(const char* device_name = BLU_NAME);

    /**
     * @brief 停止蓝牙配网
     * 
     * 停止BluFi服务，断开客户端连接，停止蓝牙广播
     * 
     * @return true 停止成功，false 停止失败
     */
    bool StopProvisioning();

    /**
     * @brief 获取当前配网状态
     * @return 当前状态
     */
    BluetoothProvisioningState GetState() const { return state_; }

    /**
     * @brief 设置事件回调函数
     * 
     * 设置用于接收配网事件通知的回调函数
     * 
     * @param callback 事件回调函数，当配网过程中发生事件时会被调用
     */
    void SetCallback(BluetoothProvisioningCallback callback) { callback_ = callback; }

    /**
     * @brief 获取最后收到的WiFi凭据
     * 
     * 返回从手机客户端接收到的WiFi连接信息
     * 
     * @return WiFi凭据结构体的常量引用
     */
    const WiFiCredentials& GetWiFiCredentials() const { return wifi_credentials_; }

    /**
     * @brief 检查是否已连接客户端
     * 
     * 检查当前是否有手机客户端连接到设备
     * 
     * @return true 已连接，false 未连接
     */
    bool IsClientConnected() const { return client_connected_; }

    /**
     * @brief 获取当前状态的字符串表示
     * 
     * 将当前配网状态转换为可读的字符串形式，便于调试和日志输出
     * 
     * @return 状态字符串
     */
    std::string GetStateString() const;

    /**
     * @brief 发送WiFi连接状态报告
     * 
     * 向手机客户端报告WiFi连接尝试的结果
     * 
     * @param success 连接是否成功
     * @param reason 失败原因代码（仅在失败时有效）
     */
    void ReportWiFiStatus(bool success, uint8_t reason = 0);

    /**
     * @brief 发送WiFi扫描结果
     * 
     * 将扫描到的WiFi接入点列表发送给手机客户端
     * 
     * @param ap_list WiFi接入点记录数组
     * @param ap_count 接入点数量
     */
    void SendWiFiList(const wifi_ap_record_t* ap_list, uint16_t ap_count);

    /**
     * @brief 可靠地发送设备MAC地址给手机客户端
     * 
     * 该函数实现了增强的MAC地址发送机制，包括：
     * - 多次重试机制，提高发送成功率
     * - 连接状态双重检查，避免竞争条件
     * - 重复发送检测，避免发送相同MAC地址
     * - 详细的错误处理和日志记录
     * 
     * @return true 发送成功，false 发送失败
     */
    bool SendMacAddressReliably();

    /**
     * @brief 重置MAC地址发送状态
     * 
     * 在新的配网会话开始时调用，清除之前的发送记录
     * 允许重新发送MAC地址
     */
    void ResetMacSendingState();

private:
    BluetoothProvisioningState state_;          //< 当前配网状态
    BluetoothProvisioningCallback callback_;    //< 用户设置的事件回调函数
    WiFiCredentials wifi_credentials_;          //< 存储接收到的WiFi凭据信息
    bool client_connected_;                     //< 客户端连接状态标志
    bool initialized_;                          //< 蓝牙配网模块初始化状态标志
    bool delayed_disconnect_;                   //< 延迟断开连接标志，用于优雅断开
    bool wifi_connecting_;                      //< WiFi连接进行中标志
    bool mac_address_sent_;                     //< MAC地址发送状态标志，避免重复发送
    
    // 静态实例指针，用于C回调函数访问
    static BluetoothProvisioning* instance_;    //< 单例实例指针，用于静态回调函数访问类成员
    
    /**
     * @brief 设置状态并触发回调
     * 
     * 内部状态管理函数，更新当前状态并通知回调函数
     * 
     * @param new_state 新的配网状态
     */
    void SetState(BluetoothProvisioningState new_state);
    
    /**
     * @brief 触发事件回调
     * 
     * 向用户注册的回调函数发送事件通知
     * 
     * @param event 事件类型
     * @param data 事件相关数据指针（可选）
     */
    void TriggerCallback(BluetoothProvisioningEvent event, void* data = nullptr);
    
public:
    /**
     * @brief BluFi事件回调函数（静态函数）
     * 
     * ESP-IDF BluFi库的静态回调函数，处理所有BluFi相关事件
     * 
     * @param event BluFi事件类型
     * @param param 事件参数结构体指针
     */
    static void BlufiEventCallback(esp_blufi_cb_event_t event, esp_blufi_cb_param_t* param);
    
private:
    /**
     * @brief WiFi事件处理函数
     * 
     * 处理WiFi连接、断开等相关事件
     * 
     * @param arg 用户参数
     * @param event_base 事件基础类型
     * @param event_id 事件ID
     * @param event_data 事件数据
     */
    static void WiFiEventHandler(void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data);
    
    /**
     * @brief IP事件处理函数
     * 
     * 处理IP地址获取等网络相关事件
     * 
     * @param arg 用户参数
     * @param event_base 事件基础类型
     * @param event_id 事件ID
     * @param event_data 事件数据
     */
    static void IPEventHandler(void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data);
    
    // 禁用拷贝构造和赋值操作
    BluetoothProvisioning(const BluetoothProvisioning&) = delete;
    BluetoothProvisioning& operator=(const BluetoothProvisioning&) = delete;
};