/**
 * @file bluetooth_provisioning_example.cc
 * @brief 蓝牙配网使用示例
 * 
 * 本文件展示了如何在ESP32项目中集成和使用蓝牙配网功能
 * 包括初始化、启动配网、处理回调事件等完整流程
 */

#include "bluetooth_provisioning.h"
#include "esp_log.h"
#include "esp_wifi.h"
#include "esp_netif.h"
#include "esp_event.h"
#include "nvs_flash.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"

#define TAG "BluetoothProvisioningExample"

// 全局蓝牙配网对象
static BluetoothProvisioning* g_bt_provisioning = nullptr;

/**
 * @brief 蓝牙配网事件回调函数
 * 
 * 处理蓝牙配网过程中的各种事件，包括状态变化、WiFi连接等
 * 
 * @param event 事件类型
 * @param data 事件数据指针
 */
void bluetooth_provisioning_callback(BluetoothProvisioningEvent event, void* data) {
    switch (event) {
    case BluetoothProvisioningEvent::STATE_CHANGED: {
        BluetoothProvisioningState state = g_bt_provisioning->GetState();
        const char* state_names[] = {
            "空闲", "初始化中", "广播中", "已连接", 
            "配网中", "成功", "失败", "已停止"
        };
        ESP_LOGI(TAG, "配网状态变更: %s", state_names[static_cast<int>(state)]);
        break;
    }
    
    case BluetoothProvisioningEvent::CLIENT_CONNECTED:
        ESP_LOGI(TAG, "蓝牙客户端已连接，可以开始配网");
        break;
        
    case BluetoothProvisioningEvent::CLIENT_DISCONNECTED:
        ESP_LOGI(TAG, "蓝牙客户端已断开连接");
        break;
        
    case BluetoothProvisioningEvent::WIFI_CREDENTIALS: {
        WiFiCredentials* credentials = static_cast<WiFiCredentials*>(data);
        ESP_LOGI(TAG, "收到WiFi凭据:");
        ESP_LOGI(TAG, "  SSID: %s", credentials->ssid.c_str());
        ESP_LOGI(TAG, "  密码长度: %d", credentials->password.length());
        if (credentials->bssid_set) {
            ESP_LOGI(TAG, "  BSSID: %02x:%02x:%02x:%02x:%02x:%02x",
                    credentials->bssid[0], credentials->bssid[1], credentials->bssid[2],
                    credentials->bssid[3], credentials->bssid[4], credentials->bssid[5]);
        }
        break;
    }
    
    case BluetoothProvisioningEvent::WIFI_CONNECTED: {
        esp_ip4_addr_t* ip = static_cast<esp_ip4_addr_t*>(data);
        ESP_LOGI(TAG, "WiFi连接成功！IP地址: " IPSTR, IP2STR(ip));
        
        // WiFi连接成功后，可以选择停止蓝牙配网以节省资源
        // 延迟5秒后停止配网，给客户端足够时间接收状态
        vTaskDelay(pdMS_TO_TICKS(5000));
        if (g_bt_provisioning) {
            g_bt_provisioning->StopProvisioning();
            ESP_LOGI(TAG, "配网成功，已停止蓝牙配网服务");
        }
        break;
    }
    
    case BluetoothProvisioningEvent::WIFI_FAILED: {
        uint8_t* reason = static_cast<uint8_t*>(data);
        ESP_LOGE(TAG, "WiFi连接失败，错误代码: %d", *reason);
        
        // WiFi连接失败，可以选择重新开始配网或进行其他处理
        ESP_LOGI(TAG, "WiFi连接失败，配网服务继续运行等待重新配置");
        break;
    }
    
    default:
        ESP_LOGW(TAG, "未处理的配网事件: %d", static_cast<int>(event));
        break;
    }
}

/**
 * @brief 初始化WiFi
 * 
 * 配置WiFi为STA模式，为蓝牙配网做准备
 */
esp_err_t init_wifi() {
    ESP_LOGI(TAG, "初始化WiFi...");
    
    // 创建默认WiFi STA网络接口
    esp_netif_create_default_wifi_sta();
    
    // 初始化WiFi配置
    wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
    esp_err_t ret = esp_wifi_init(&cfg);
    if (ret != ESP_OK) {
        ESP_LOGE(TAG, "WiFi初始化失败: %s", esp_err_to_name(ret));
        return ret;
    }
    
    // 设置WiFi模式为STA
    ret = esp_wifi_set_mode(WIFI_MODE_STA);
    if (ret != ESP_OK) {
        ESP_LOGE(TAG, "WiFi模式设置失败: %s", esp_err_to_name(ret));
        return ret;
    }
    
    // 启动WiFi
    ret = esp_wifi_start();
    if (ret != ESP_OK) {
        ESP_LOGE(TAG, "WiFi启动失败: %s", esp_err_to_name(ret));
        return ret;
    }
    
    ESP_LOGI(TAG, "WiFi初始化完成");
    return ESP_OK;
}

/**
 * @brief 蓝牙配网任务
 * 
 * 独立任务处理蓝牙配网的整个生命周期
 * 
 * @param pvParameters 任务参数（未使用）
 */
void bluetooth_provisioning_task(void* pvParameters) {
    ESP_LOGI(TAG, "启动蓝牙配网任务");
    
    // 1. 创建蓝牙配网对象
    g_bt_provisioning = new BluetoothProvisioning();
    if (g_bt_provisioning == nullptr) {
        ESP_LOGE(TAG, "蓝牙配网对象创建失败");
        vTaskDelete(nullptr);
        return;
    }
    
    // 2. 设置事件回调
    g_bt_provisioning->SetCallback(bluetooth_provisioning_callback);
    
    // 3. 初始化蓝牙配网
    if (!g_bt_provisioning->Initialize()) {
        ESP_LOGE(TAG, "蓝牙配网初始化失败");
        delete g_bt_provisioning;
        g_bt_provisioning = nullptr;
        vTaskDelete(nullptr);
        return;
    }
    
    // 4. 启动配网服务 (设备名自动构建: Airhub_ + BLE MAC)
    if (!g_bt_provisioning->StartProvisioning()) {
        ESP_LOGE(TAG, "蓝牙配网启动失败");
        g_bt_provisioning->Deinitialize();
        delete g_bt_provisioning;
        g_bt_provisioning = nullptr;
        vTaskDelete(nullptr);
        return;
    }
    
    ESP_LOGI(TAG, "蓝牙配网服务已启动，设备名称: %s", device_name);
    ESP_LOGI(TAG, "请使用ESP-IDF官方配网APP或自定义APP进行配网");
    
    // 5. 任务主循环 - 监控配网状态
    while (true) {
        BluetoothProvisioningState state = g_bt_provisioning->GetState();
        
        // 检查是否需要处理特殊状态
        switch (state) {
        case BluetoothProvisioningState::SUCCESS:
            ESP_LOGI(TAG, "配网成功完成");
            // 可以在这里添加配网成功后的处理逻辑
            break;
            
        case BluetoothProvisioningState::FAILED:
            ESP_LOGE(TAG, "配网失败，尝试重新启动");
            // 配网失败，尝试重新启动
            g_bt_provisioning->StopProvisioning();
            vTaskDelay(pdMS_TO_TICKS(2000));
            g_bt_provisioning->StartProvisioning(device_name);
            break;
            
        case BluetoothProvisioningState::STOPPED:
            ESP_LOGI(TAG, "配网服务已停止");
            // 配网服务已停止，可以选择退出任务或重新启动
            break;
            
        default:
            // 其他状态正常运行
            break;
        }
        
        // 每5秒检查一次状态
        vTaskDelay(pdMS_TO_TICKS(5000));
    }
    
    // 清理资源（通常不会执行到这里）
    if (g_bt_provisioning) {
        g_bt_provisioning->Deinitialize();
        delete g_bt_provisioning;
        g_bt_provisioning = nullptr;
    }
    
    vTaskDelete(nullptr);
}

/**
 * @brief 应用程序主函数
 * 
 * 演示如何集成蓝牙配网到现有的ESP32应用程序中
 */
extern "C" void app_main() {
    ESP_LOGI(TAG, "=== 蓝牙配网示例程序启动 ===");
    
    // 1. 初始化NVS（用于存储WiFi配置）
    esp_err_t ret = nvs_flash_init();
    if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
        ESP_ERROR_CHECK(nvs_flash_erase());
        ret = nvs_flash_init();
    }
    ESP_ERROR_CHECK(ret);
    
    // 2. 初始化网络接口
    ESP_ERROR_CHECK(esp_netif_init());
    
    // 3. 创建默认事件循环
    ESP_ERROR_CHECK(esp_event_loop_create_default());
    
    // 4. 初始化WiFi
    ESP_ERROR_CHECK(init_wifi());
    
    // 5. 创建蓝牙配网任务
    BaseType_t task_ret = xTaskCreate(
        bluetooth_provisioning_task,    // 任务函数
        "bt_provisioning",              // 任务名称
        8192,                           // 栈大小（字节）
        nullptr,                        // 任务参数
        5,                              // 任务优先级
        nullptr                         // 任务句柄
    );
    
    if (task_ret != pdPASS) {
        ESP_LOGE(TAG, "蓝牙配网任务创建失败");
        return;
    }
    
    ESP_LOGI(TAG, "应用程序初始化完成");
    
    // 6. 主程序循环（可以在这里添加其他应用逻辑）
    while (true) {
        // 这里可以添加应用程序的主要逻辑
        // 例如：传感器读取、数据处理、用户交互等
        
        ESP_LOGI(TAG, "主程序运行中...");
        vTaskDelay(pdMS_TO_TICKS(30000)); // 每30秒打印一次状态
    }
}

/**
 * @brief 获取当前配网状态（供其他模块调用）
 * 
 * @return BluetoothProvisioningState 当前配网状态
 */
BluetoothProvisioningState get_provisioning_state() {
    if (g_bt_provisioning) {
        return g_bt_provisioning->GetState();
    }
    return BluetoothProvisioningState::STOPPED;
}

/**
 * @brief 检查WiFi是否已连接（供其他模块调用）
 * 
 * @return true WiFi已连接
 * @return false WiFi未连接
 */
bool is_wifi_connected() {
    BluetoothProvisioningState state = get_provisioning_state();
    return (state == BluetoothProvisioningState::SUCCESS);
}

/**
 * @brief 手动启动配网（供其他模块调用）
 * 
 * 可以在用户按下配网按钮或其他触发条件时调用
 * 
 * @return true 启动成功
 * @return false 启动失败
 */
bool start_provisioning_manually() {
    if (g_bt_provisioning == nullptr) {
        ESP_LOGE(TAG, "蓝牙配网对象未初始化");
        return false;
    }
    
    BluetoothProvisioningState state = g_bt_provisioning->GetState();
    if (state == BluetoothProvisioningState::ADVERTISING ||
        state == BluetoothProvisioningState::CONNECTED ||
        state == BluetoothProvisioningState::PROVISIONING) {
        ESP_LOGW(TAG, "配网已在运行中");
        return true;
    }
    
    ESP_LOGI(TAG, "手动启动蓝牙配网");
    return g_bt_provisioning->StartProvisioning("小智AI-手动配网");
}

/**
 * @brief 手动停止配网（供其他模块调用）
 * 
 * @return true 停止成功
 * @return false 停止失败
 */
bool stop_provisioning_manually() {
    if (g_bt_provisioning == nullptr) {
        ESP_LOGE(TAG, "蓝牙配网对象未初始化");
        return false;
    }
    
    ESP_LOGI(TAG, "手动停止蓝牙配网");
    return g_bt_provisioning->StopProvisioning();
}