/**
 * @file bluetooth_provisioning_test.cc
 * @brief 蓝牙配网功能测试文件
 * @author AI Assistant
 * @date 2024-01-01
 */

#include "bluetooth_provisioning.h"
#include "bluetooth_provisioning_config.h"
#include <cstring>
#include <cassert>
#include <iostream>
#include <chrono>
#include <thread>

// 为了避免IDE环境中的头文件错误，使用条件编译
#ifdef ESP_PLATFORM
#include "esp_wifi.h"
#include "esp_netif.h"
#include "esp_event.h"
#include "nvs_flash.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/event_groups.h"
#include "esp_log.h"
#else
// 在非ESP环境中定义必要的宏和类型
#define ESP_LOGI(tag, format, ...) printf("[INFO][%s] " format "\n", tag, ##__VA_ARGS__)
#define ESP_LOGE(tag, format, ...) printf("[ERROR][%s] " format "\n", tag, ##__VA_ARGS__)
#define ESP_LOGW(tag, format, ...) printf("[WARN][%s] " format "\n", tag, ##__VA_ARGS__)
#define pdMS_TO_TICKS(ms) (ms)
typedef void* TaskHandle_t;
void vTaskDelay(int ticks) { std::this_thread::sleep_for(std::chrono::milliseconds(ticks)); }
void vTaskDelete(TaskHandle_t task) { (void)task; }
int xTaskCreate(void (*task_func)(void*), const char* name, int stack_size, void* params, int priority, TaskHandle_t* handle) {
    (void)task_func; (void)name; (void)stack_size; (void)params; (void)priority; (void)handle;
    return 1; // 模拟成功
}
#endif

#define TAG "BluetoothProvisioningTest"

// 测试事件组
static EventGroupHandle_t test_event_group = nullptr;
#define TEST_WIFI_CONNECTED_BIT BIT0
#define TEST_WIFI_FAILED_BIT    BIT1
#define TEST_BT_CONNECTED_BIT   BIT2
#define TEST_TIMEOUT_BIT        BIT3

// 测试结果统计
static struct {
    int total_tests;
    int passed_tests;
    int failed_tests;
} test_stats = {0, 0, 0};

/**
 * @brief 测试事件回调函数
 */
void test_provisioning_callback(BluetoothProvisioningEvent event, void* data) {
    switch (event) {
    case BluetoothProvisioningEvent::STATE_CHANGED:
        ESP_LOGI(TAG, "[测试] 配网状态变更");
        break;
        
    case BluetoothProvisioningEvent::CLIENT_CONNECTED:
        ESP_LOGI(TAG, "[测试] 蓝牙客户端已连接");
        xEventGroupSetBits(test_event_group, TEST_BT_CONNECTED_BIT);
        break;
        
    case BluetoothProvisioningEvent::CLIENT_DISCONNECTED:
        ESP_LOGI(TAG, "[测试] 蓝牙客户端已断开");
        xEventGroupClearBits(test_event_group, TEST_BT_CONNECTED_BIT);
        break;
        
    case BluetoothProvisioningEvent::WIFI_CREDENTIALS: {
        WiFiCredentials* credentials = static_cast<WiFiCredentials*>(data);
        ESP_LOGI(TAG, "[测试] 收到WiFi凭据: SSID=%s", credentials->ssid.c_str());
        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));
        xEventGroupSetBits(test_event_group, TEST_WIFI_CONNECTED_BIT);
        break;
    }
    
    case BluetoothProvisioningEvent::WIFI_FAILED: {
        uint8_t* reason = static_cast<uint8_t*>(data);
        ESP_LOGE(TAG, "[测试] WiFi连接失败: 原因=%d", *reason);
        xEventGroupSetBits(test_event_group, TEST_WIFI_FAILED_BIT);
        break;
    }
    
    default:
        ESP_LOGD(TAG, "[测试] 未处理的事件: %d", static_cast<int>(event));
        break;
    }
}

/**
 * @brief 测试辅助函数 - 记录测试结果
 */
void record_test_result(const char* test_name, bool passed) {
    test_stats.total_tests++;
    if (passed) {
        test_stats.passed_tests++;
        ESP_LOGI(TAG, "✅ [测试通过] %s", test_name);
    } else {
        test_stats.failed_tests++;
        ESP_LOGE(TAG, "❌ [测试失败] %s", test_name);
    }
}

/**
 * @brief 测试1：基本初始化和反初始化
 */
bool test_basic_initialization() {
    ESP_LOGI(TAG, "开始测试：基本初始化和反初始化");
    
    BluetoothProvisioning* prov = new BluetoothProvisioning();
    if (!prov) {
        return false;
    }
    
    // 测试初始化
    bool init_result = prov->Initialize();
    if (!init_result) {
        delete prov;
        return false;
    }
    
    // 检查初始状态
    BluetoothProvisioningState state = prov->GetState();
    if (state != BluetoothProvisioningState::IDLE) {
        prov->Deinitialize();
        delete prov;
        return false;
    }
    
    // 测试反初始化
    bool deinit_result = prov->Deinitialize();
    delete prov;
    
    return init_result && deinit_result;
}

/**
 * @brief 测试2：配网服务启动和停止
 */
bool test_provisioning_start_stop() {
    ESP_LOGI(TAG, "开始测试：配网服务启动和停止");
    
    BluetoothProvisioning* prov = new BluetoothProvisioning();
    if (!prov || !prov->Initialize()) {
        delete prov;
        return false;
    }
    
    // 测试启动配网
    bool start_result = prov->StartProvisioning("测试设备");
    if (!start_result) {
        prov->Deinitialize();
        delete prov;
        return false;
    }
    
    // 检查状态
    BluetoothProvisioningState state = prov->GetState();
    if (state != BluetoothProvisioningState::ADVERTISING) {
        prov->Deinitialize();
        delete prov;
        return false;
    }
    
    // 等待一段时间
    vTaskDelay(pdMS_TO_TICKS(2000));
    
    // 测试停止配网
    bool stop_result = prov->StopProvisioning();
    
    // 检查状态
    state = prov->GetState();
    bool state_ok = (state == BluetoothProvisioningState::IDLE);
    
    prov->Deinitialize();
    delete prov;
    
    return start_result && stop_result && state_ok;
}

/**
 * @brief 测试3：回调函数设置和触发
 */
bool test_callback_functionality() {
    ESP_LOGI(TAG, "开始测试：回调函数设置和触发");
    
    BluetoothProvisioning* prov = new BluetoothProvisioning();
    if (!prov || !prov->Initialize()) {
        delete prov;
        return false;
    }
    
    // 设置回调函数
    prov->SetCallback(test_provisioning_callback);
    
    // 启动配网（这会触发状态变更回调）
    bool start_result = prov->StartProvisioning("回调测试设备");
    
    // 等待回调触发
    vTaskDelay(pdMS_TO_TICKS(1000));
    
    // 停止配网
    prov->StopProvisioning();
    prov->Deinitialize();
    delete prov;
    
    return start_result;
}

/**
 * @brief 测试4：状态管理
 */
bool test_state_management() {
    ESP_LOGI(TAG, "开始测试：状态管理");
    
    BluetoothProvisioning* prov = new BluetoothProvisioning();
    if (!prov) {
        return false;
    }
    
    // 检查初始状态
    BluetoothProvisioningState state = prov->GetState();
    if (state != BluetoothProvisioningState::IDLE) {
        delete prov;
        return false;
    }
    
    // 初始化后检查状态
    if (!prov->Initialize()) {
        delete prov;
        return false;
    }
    
    state = prov->GetState();
    if (state != BluetoothProvisioningState::IDLE) {
        prov->Deinitialize();
        delete prov;
        return false;
    }
    
    // 启动配网后检查状态
    prov->StartProvisioning("状态测试设备");
    state = prov->GetState();
    bool advertising_state_ok = (state == BluetoothProvisioningState::ADVERTISING);
    
    // 停止配网后检查状态
    prov->StopProvisioning();
    state = prov->GetState();
    bool idle_state_ok = (state == BluetoothProvisioningState::IDLE);
    
    prov->Deinitialize();
    delete prov;
    
    return advertising_state_ok && idle_state_ok;
}

/**
 * @brief 测试5：错误处理
 */
bool test_error_handling() {
    ESP_LOGI(TAG, "开始测试：错误处理");
    
    BluetoothProvisioning* prov = new BluetoothProvisioning();
    if (!prov) {
        return false;
    }
    
    // 测试未初始化时启动配网
    bool should_fail = prov->StartProvisioning("错误测试设备");
    if (should_fail) {
        // 这应该失败
        delete prov;
        return false;
    }
    
    // 正常初始化
    if (!prov->Initialize()) {
        delete prov;
        return false;
    }
    
    // 测试重复初始化
    bool repeat_init = prov->Initialize();
    if (!repeat_init) {
        // 重复初始化应该返回true（已经初始化）
        prov->Deinitialize();
        delete prov;
        return false;
    }
    
    // 测试重复启动配网
    prov->StartProvisioning("错误测试设备1");
    bool repeat_start = prov->StartProvisioning("错误测试设备2");
    if (!repeat_start) {
        // 重复启动应该返回true（已经在运行）
        prov->Deinitialize();
        delete prov;
        return false;
    }
    
    prov->StopProvisioning();
    prov->Deinitialize();
    delete prov;
    
    return true;
}

/**
 * @brief 测试6：内存管理
 */
bool test_memory_management() {
    ESP_LOGI(TAG, "开始测试：内存管理");
    
    size_t free_heap_before = esp_get_free_heap_size();
    ESP_LOGI(TAG, "测试前可用内存: %d 字节", free_heap_before);
    
    // 创建和销毁多个实例
    for (int i = 0; i < 3; i++) {
        BluetoothProvisioning* prov = new BluetoothProvisioning();
        if (!prov) {
            return false;
        }
        
        if (prov->Initialize()) {
            prov->StartProvisioning("内存测试设备");
            vTaskDelay(pdMS_TO_TICKS(500));
            prov->StopProvisioning();
            prov->Deinitialize();
        }
        
        delete prov;
        vTaskDelay(pdMS_TO_TICKS(100));
    }
    
    size_t free_heap_after = esp_get_free_heap_size();
    ESP_LOGI(TAG, "测试后可用内存: %d 字节", free_heap_after);
    
    // 检查内存泄漏（允许一定的误差）
    int memory_diff = free_heap_before - free_heap_after;
    bool memory_ok = (memory_diff < 1024); // 允许1KB的误差
    
    if (!memory_ok) {
        ESP_LOGW(TAG, "可能存在内存泄漏: %d 字节", memory_diff);
    }
    
    return memory_ok;
}

/**
 * @brief 运行所有测试
 */
void run_all_tests() {
    ESP_LOGI(TAG, "=== 开始蓝牙配网功能测试 ===");
    
    // 创建测试事件组
    test_event_group = xEventGroupCreate();
    if (!test_event_group) {
        ESP_LOGE(TAG, "测试事件组创建失败");
        return;
    }
    
    // 运行各项测试
    record_test_result("基本初始化和反初始化", test_basic_initialization());
    record_test_result("配网服务启动和停止", test_provisioning_start_stop());
    record_test_result("回调函数设置和触发", test_callback_functionality());
    record_test_result("状态管理", test_state_management());
    record_test_result("错误处理", test_error_handling());
    record_test_result("内存管理", test_memory_management());
    
    // 输出测试结果
    ESP_LOGI(TAG, "=== 测试结果统计 ===");
    ESP_LOGI(TAG, "总测试数: %d", test_stats.total_tests);
    ESP_LOGI(TAG, "通过测试: %d", test_stats.passed_tests);
    ESP_LOGI(TAG, "失败测试: %d", test_stats.failed_tests);
    
    if (test_stats.failed_tests == 0) {
        ESP_LOGI(TAG, "🎉 所有测试通过！蓝牙配网功能正常");
    } else {
        ESP_LOGE(TAG, "⚠️  有 %d 个测试失败，请检查实现", test_stats.failed_tests);
    }
    
    // 清理资源
    vEventGroupDelete(test_event_group);
    test_event_group = nullptr;
}

/**
 * @brief 蓝牙配网测试任务
 */
void bluetooth_provisioning_test_task(void* pvParameters) {
    ESP_LOGI(TAG, "蓝牙配网测试任务启动");
    
    // 等待系统稳定
    vTaskDelay(pdMS_TO_TICKS(2000));
    
    // 运行测试
    run_all_tests();
    
    ESP_LOGI(TAG, "蓝牙配网测试任务完成");
    vTaskDelete(nullptr);
}

/**
 * @brief 启动蓝牙配网测试
 * 
 * 在主程序中调用此函数来启动测试
 */
void start_bluetooth_provisioning_test() {
    BaseType_t ret = xTaskCreate(
        bluetooth_provisioning_test_task,
        "bt_prov_test",
        8192,
        nullptr,
        3,  // 较低优先级
        nullptr
    );
    
    if (ret != pdPASS) {
        ESP_LOGE(TAG, "蓝牙配网测试任务创建失败");
    } else {
        ESP_LOGI(TAG, "蓝牙配网测试任务已创建");
    }
}

/**
 * @brief 简单的配网功能演示
 * 
 * 演示如何使用蓝牙配网功能
 */
void bluetooth_provisioning_demo() {
    ESP_LOGI(TAG, "=== 蓝牙配网功能演示 ===");
    
    BluetoothProvisioning* prov = new BluetoothProvisioning();
    if (!prov) {
        ESP_LOGE(TAG, "配网对象创建失败");
        return;
    }
    
    // 设置回调
    prov->SetCallback(test_provisioning_callback);
    
    // 初始化
    if (!prov->Initialize()) {
        ESP_LOGE(TAG, "配网初始化失败");
        delete prov;
        return;
    }
    
    // 启动配网
    if (!prov->StartProvisioning("小智AI-演示")) {
        ESP_LOGE(TAG, "配网启动失败");
        prov->Deinitialize();
        delete prov;
        return;
    }
    
    ESP_LOGI(TAG, "配网服务已启动，请使用配网APP连接设备");
    ESP_LOGI(TAG, "设备名称: 小智AI-演示");
    ESP_LOGI(TAG, "等待客户端连接...");
    
    // 运行30秒演示
    for (int i = 0; i < 30; i++) {
        BluetoothProvisioningState state = prov->GetState();
        const char* state_names[] = {
            "空闲", "初始化中", "广播中", "已连接", 
            "配网中", "成功", "失败", "已停止"
        };
        
        ESP_LOGI(TAG, "当前状态: %s, 客户端连接: %s", 
                state_names[static_cast<int>(state)],
                prov->IsClientConnected() ? "是" : "否");
        
        if (state == BluetoothProvisioningState::SUCCESS) {
            ESP_LOGI(TAG, "配网成功！演示结束");
            break;
        }
        
        vTaskDelay(pdMS_TO_TICKS(1000));
    }
    
    // 清理资源
    prov->StopProvisioning();
    prov->Deinitialize();
    delete prov;
    
    ESP_LOGI(TAG, "演示结束");
}