#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_log.h"
#include "esp_bt.h"
#include "esp_gap_ble_api.h"
#include "esp_gatts_api.h"
#include "esp_bt_main.h"
#include "esp_bt_device.h"
#include "esp_gatt_common_api.h"
#include "esp_mac.h"
#include "fatfs.h"
#include "pages.h"
#include <stdbool.h>
#include "ble_transfer.h"
#include "key_nav.h"
#include "esp_lvgl_port.h"
#include "ui/ui.h"
#include "ui/screens/ui_ScreenReceiving.h"
#include "ui/screens/ui_ScreenUpdate.h"

// BLE广播控制标志（开机默认关闭，需按键启动）
static bool ble_advertising_enabled = false;


#define APP_ID_PLACEHOLDER 0

#define IMAGE_SERVICE_INSTID 0x0B
#define IMAGE_SERVICE_UUID 0x0B00
#define IMAGE_WRITE_UUID 0x0B01
#define IMAGE_EDIT_UUID 0x0B02

static uint16_t image_service_handle = 0;
static uint16_t image_write_handle = 0;
static uint16_t image_edit_handle = 0;

static void esp_gap_cb(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param);
static void gatts_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t *param);
void ble_stop(void);  // 前向声明（定义在文件末尾）


static const char *CONN_TAG = "CONN_BLE";
static char ble_device_name[32];
static uint8_t adv_raw_len = 0;

static uint16_t conn_id;

static char *filepath;

typedef struct
{
    uint8_t type;
    char filename[23];
    uint32_t len;
} Megtype;

typedef struct{
    bool isSend;
    uint32_t port;
} MegStatus;

Megtype firstMeg;
MegStatus SendStatus = {false,0};

uint8_t *img_data = 0;
FILE *file_img;

// BLE 图片处理任务（NVS 写入 + 导航显示在独立任务中执行，避免 BTC_TASK 栈溢出）
static TaskHandle_t ble_process_task_handle = NULL;
static char ble_pending_filename[24];
static uint8_t *ble_pending_data = NULL;   // 传输完成的图片数据（直通显示，跳过 SPIFFS 重读）
static size_t ble_pending_data_size = 0;

static void ble_process_task(void *arg) {
    while (1) {
        ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
        nvs_change_img(ble_pending_filename);
        ble_image_navigate_with_data(ble_pending_filename, ble_pending_data, ble_pending_data_size);
        ble_pending_data = NULL;  // 所有权已转移，不再释放
        ble_pending_data_size = 0;

        // 确保导航上下文为Img（APP传图和设备间传图统一处理）
        ESP_LOGI(CONN_TAG, "传图完成：切换到Img界面，关闭蓝牙");
        key_nav_set_context(NAV_CTX_IMG);

        // 传图完成后关闭蓝牙节省资源（对APP传图和设备间传图都适用）
        ble_stop();
    }
}

static uint8_t attr_value_write[512] = {0};
static uint8_t attr_value_edit[20] = {0};

static esp_attr_value_t char_val_image_write = {
    .attr_max_len = 512,
    .attr_len = 512,
    .attr_value = attr_value_write
} ;
static esp_attr_value_t char_val_image_edit = {
    .attr_max_len = 20,
    .attr_len = 20,
    .attr_value = attr_value_edit
} ;

static esp_attr_control_t control_image_write = {
    .auto_rsp = ESP_GATT_AUTO_RSP
};
static esp_attr_control_t control_image_edit = {
    .auto_rsp = ESP_GATT_AUTO_RSP
};

// 图片传输服务
static esp_gatt_srvc_id_t server_id_image = {
    .id.uuid.len = ESP_UUID_LEN_16,
    .id.uuid.uuid.uuid16 = IMAGE_SERVICE_UUID,
    .id.inst_id = IMAGE_SERVICE_INSTID,
    .is_primary = true,
};
static esp_bt_uuid_t image_write_uuid = {
    .len = ESP_UUID_LEN_16,
    .uuid.uuid16 = IMAGE_WRITE_UUID,
};
static esp_bt_uuid_t image_edit_uuid = {
    .len = ESP_UUID_LEN_16,
    .uuid.uuid16 = IMAGE_EDIT_UUID,
};


static esp_ble_adv_params_t adv_params = {
    .adv_int_min = 0x20,
    .adv_int_max = 0x20,
    .adv_type = ADV_TYPE_IND,
    .own_addr_type = BLE_ADDR_TYPE_PUBLIC,
    .channel_map = ADV_CHNL_ALL,
    .adv_filter_policy = ADV_FILTER_ALLOW_SCAN_ANY_CON_ANY,
};


static uint8_t adv_raw_data[31];

// Scan Response 数据：厂商标识 + 服务UUID
static uint8_t scan_rsp_data[] = {
    0x07, ESP_BLE_AD_MANUFACTURER_SPECIFIC_TYPE, 0x4C, 0x44, 0x64, 0x7A, 0x62, 0x6A, // "LDdzbj"
    0x03, ESP_BLE_AD_TYPE_16SRV_CMPL, 0x00, 0x0B,  // 服务UUID 0x0B00
};


void ble_init(void)
{
    esp_err_t ret;
    ESP_ERROR_CHECK(esp_bt_controller_mem_release(ESP_BT_MODE_CLASSIC_BT));
    esp_bt_controller_config_t bt_cfg = BT_CONTROLLER_INIT_CONFIG_DEFAULT();
    ret = esp_bt_controller_init(&bt_cfg);
    if (ret) {
        ESP_LOGE(CONN_TAG, "%s initialize controller failed: %s", __func__, esp_err_to_name(ret));
        return;
    }
    ret = esp_bt_controller_enable(ESP_BT_MODE_BLE);
    if (ret) {
        ESP_LOGE(CONN_TAG, "%s enable controller failed: %s", __func__, esp_err_to_name(ret));
        return;
    }
    ret = esp_bluedroid_init();
    if (ret) {
        ESP_LOGE(CONN_TAG, "%s init bluetooth failed: %s", __func__, esp_err_to_name(ret));
        return;
    }
    ret = esp_bluedroid_enable();
    if (ret) {
        ESP_LOGE(CONN_TAG, "%s enable bluetooth failed: %s", __func__, esp_err_to_name(ret));
        return;
    }
    ret = esp_ble_gap_register_callback(esp_gap_cb);
    if (ret) {
        ESP_LOGE(CONN_TAG, "%s gap register failed, error code = %x", __func__, ret);
        return;
    }

    ret = esp_ble_gatts_register_callback(gatts_event_handler);
    if (ret) {
        ESP_LOGE(CONN_TAG, "%s gatts register failed, error code = %x", __func__, ret);
        return;
    }
    ret = esp_ble_gatts_app_register(APP_ID_PLACEHOLDER);
    if (ret) {
        ESP_LOGE(CONN_TAG, "%s gatts app register failed, error code = %x", __func__, ret);
        return;
    }
    ret = esp_ble_gatt_set_local_mtu(512);
    if (ret) {
        ESP_LOGE(CONN_TAG, "set local  MTU failed, error code = %x", ret);
        return;
    }

    // 获取 BLE MAC 地址并构建设备名称: Airhub_xx:xx:xx:xx:xx:xx
    const uint8_t *ble_addr = esp_bt_dev_get_address();
    if (ble_addr) {
        snprintf(ble_device_name, sizeof(ble_device_name),
                 "Airhub_%02x:%02x:%02x:%02x:%02x:%02x",
                 ble_addr[0], ble_addr[1], ble_addr[2],
                 ble_addr[3], ble_addr[4], ble_addr[5]);
        ESP_LOGI(CONN_TAG, "BLE MAC: %02x:%02x:%02x:%02x:%02x:%02x",
                 ble_addr[0], ble_addr[1], ble_addr[2],
                 ble_addr[3], ble_addr[4], ble_addr[5]);
    } else {
        strcpy(ble_device_name, "Airhub_BLE");
        ESP_LOGW(CONN_TAG, "获取BLE MAC失败，使用默认名称: %s", ble_device_name);
    }

    ret = esp_ble_gap_set_device_name(ble_device_name);
    if (ret) {
        ESP_LOGE(CONN_TAG, "set device name failed, error code = %x", ret);
        return;
    }
    ESP_LOGI(CONN_TAG, "蓝牙设备名称: %s", ble_device_name);

    // 构建广播数据: Flags + Complete Local Name
    uint8_t name_len = strlen(ble_device_name);
    int offset = 0;
    adv_raw_data[offset++] = 0x02;
    adv_raw_data[offset++] = ESP_BLE_AD_TYPE_FLAG;
    adv_raw_data[offset++] = 0x06;
    adv_raw_data[offset++] = name_len + 1;
    adv_raw_data[offset++] = ESP_BLE_AD_TYPE_NAME_CMPL;
    memcpy(&adv_raw_data[offset], ble_device_name, name_len);
    offset += name_len;
    adv_raw_len = offset;

    ret = esp_ble_gap_config_adv_data_raw(adv_raw_data, adv_raw_len);
    if (ret) {
        ESP_LOGE(CONN_TAG, "config adv data failed, error code = %x", ret);
    }

    // 配置 Scan Response 数据（厂商标识 "dzbj" + 服务UUID）
    ret = esp_ble_gap_config_scan_rsp_data_raw(scan_rsp_data, sizeof(scan_rsp_data));
    if (ret) {
        ESP_LOGE(CONN_TAG, "config scan response data failed, error code = %x", ret);
    }

    // 创建图片处理任务（8KB 栈，足够 SPIFFS 扫描 + LVGL + GIF 解码）
    xTaskCreate(ble_process_task, "ble_img", 8192, NULL, 5, &ble_process_task_handle);
}



static void esp_gap_cb(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param)
{
    switch (event) {
        case ESP_GAP_BLE_ADV_DATA_RAW_SET_COMPLETE_EVT:
            ESP_LOGI(CONN_TAG, "Advertising data set, status %d", param->adv_data_raw_cmpl.status);
            // ADV 数据设置完成，等待 Scan Response 也设置完成后再开始广播
            break;
        case ESP_GAP_BLE_SCAN_RSP_DATA_RAW_SET_COMPLETE_EVT:
            ESP_LOGI(CONN_TAG, "Scan response data set, status %d", param->scan_rsp_data_raw_cmpl.status);
            // 仅在广播已启用时开始广播（开机默认不广播）
            if (ble_advertising_enabled) {
                esp_ble_gap_start_advertising(&adv_params);
            }
            break;
        case ESP_GAP_BLE_ADV_START_COMPLETE_EVT:
            if (param->adv_start_cmpl.status != ESP_BT_STATUS_SUCCESS) {
                ESP_LOGE(CONN_TAG, "Advertising start failed, status %d", param->adv_start_cmpl.status);
                break;
            }
            ESP_LOGI(CONN_TAG, "Advertising start successfully");
            break;
        case ESP_GAP_BLE_ADV_STOP_COMPLETE_EVT:
            if (param->adv_stop_cmpl.status != ESP_BT_STATUS_SUCCESS) {
                ESP_LOGE(CONN_TAG, "Advertising stop failed, status %d", param->adv_stop_cmpl.status);
            }
            ESP_LOGI(CONN_TAG, "Advertising stop successfully");
            break;
        case ESP_GAP_BLE_SCAN_PARAM_SET_COMPLETE_EVT:
            // 扫描参数设置完成，开始扫描5秒
            esp_ble_gap_start_scanning(5);
            break;
        case ESP_GAP_BLE_SCAN_RESULT_EVT:
            // 扫描结果转发给传输模块
            ble_transfer_handle_scan_result(param);
            break;
        case ESP_GAP_BLE_SCAN_STOP_COMPLETE_EVT:
            ESP_LOGI(CONN_TAG, "Scan stopped");
            ble_transfer_handle_scan_stop();
            break;
        case ESP_GAP_BLE_UPDATE_CONN_PARAMS_EVT:
            ESP_LOGI(CONN_TAG, "Connection params update, status %d, conn_int %d, latency %d, timeout %d",
                        param->update_conn_params.status,
                        param->update_conn_params.conn_int,
                        param->update_conn_params.latency,
                        param->update_conn_params.timeout);
            break;
        case ESP_GAP_BLE_PHY_UPDATE_COMPLETE_EVT:
            ESP_LOGI(CONN_TAG, "PHY update, status %d, tx_phy %d, rx_phy %d",
                        param->phy_update.status,
                        param->phy_update.tx_phy,
                        param->phy_update.rx_phy);
            // tx_phy/rx_phy: 1=1M, 2=2M, 3=Coded
            break;
        default:
            break;
    }
}

// GATT服务器事件处理函数
static void gatts_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t *param)
{
    switch (event) {
        case ESP_GATTS_REG_EVT:
            ESP_LOGI(CONN_TAG, "GATT server register, status %d, app_id %d",param->reg.status, param->reg.app_id);
            // 创建图片传输服务
            esp_ble_gatts_create_service(gatts_if,&server_id_image,10);
            break;
        case ESP_GATTS_CREATE_EVT:
            if (param->create.status == ESP_GATT_OK) {
                image_service_handle = param->create.service_handle;
                esp_ble_gatts_add_char(
                    image_service_handle,
                    &image_write_uuid,
                    ESP_GATT_PERM_WRITE,
                    ESP_GATT_CHAR_PROP_BIT_WRITE | ESP_GATT_CHAR_PROP_BIT_WRITE_NR,
                    &char_val_image_write,
                    &control_image_write
                );
                esp_ble_gatts_add_char(
                    image_service_handle,
                    &image_edit_uuid,
                    ESP_GATT_PERM_WRITE,
                    ESP_GATT_CHAR_PROP_BIT_WRITE | ESP_GATT_CHAR_PROP_BIT_WRITE_NR,
                    &char_val_image_edit,
                    &control_image_edit
                );
                ESP_LOGI(CONN_TAG, "图片传输服务创建成功，句柄: %x", image_service_handle);
            } else {
                ESP_LOGE(CONN_TAG, "服务创建失败，状态: %d", param->create.status);
            }
            break;

        case ESP_GATTS_ADD_CHAR_EVT:
            if (param->add_char.status == ESP_GATT_OK) {
                if (param->add_char.char_uuid.uuid.uuid16 == (uint16_t)IMAGE_WRITE_UUID) {
                    image_write_handle = param->add_char.attr_handle;
                    ESP_LOGI(CONN_TAG, "图片写入特征创建成功,句柄: %d", image_write_handle);
                } else if (param->add_char.char_uuid.uuid.uuid16 == (uint16_t)IMAGE_EDIT_UUID) {
                    image_edit_handle = param->add_char.attr_handle;
                    ESP_LOGI(CONN_TAG, "图片编辑特征创建成功,句柄: %d", image_edit_handle);
                    esp_ble_gatts_start_service(image_service_handle);
                }
            } else {
                ESP_LOGE(CONN_TAG, "特征创建失败，状态: %d", param->add_char.status);
            }
            break;
        case ESP_GATTS_WRITE_EVT:
            if(param->write.handle == image_write_handle){
                uint8_t *value = param->write.value;
                if(!SendStatus.isSend){
                    ESP_LOGI(CONN_TAG, "处理前序数据");
                    firstMeg.type = value[0];
                    memcpy(firstMeg.filename, value + 1, 22);
                    firstMeg.filename[22] = '\0';
                    firstMeg.len = (value[23] << 16) | (value[24] << 8) | value[25];
                    ESP_LOGI(CONN_TAG, "图片数据长度：%d",(int)firstMeg.len);
                    if(firstMeg.type == 0xfd){
                        SendStatus.isSend = true;
                        img_data = malloc((int)firstMeg.len);
                        filepath = malloc(sizeof(char) * 33);
                        sprintf(filepath,"/spiflash/%s",firstMeg.filename);
                        file_img = fopen(filepath,"wb");
                        ESP_LOGI(CONN_TAG,"传输通道建立成功,数据指针：%p,文件名称:%s,文件大小:%d",img_data,firstMeg.filename,(int)firstMeg.len);

                        // 根据传输来源切换界面
                        if (ble_transfer_is_receiving()) {
                            // 设备间传输：切换到接收中界面
                            if (lvgl_port_lock(100)) {
                                _ui_screen_change(&ui_ScreenReceiving, LV_SCR_LOAD_ANIM_NONE, 0, 0, &ui_ScreenReceiving_screen_init);
                                lvgl_port_unlock();
                            }
                            key_nav_set_context(NAV_CTX_RECEIVING);
                        } else {
                            // APP传图：切换到Update更新界面
                            ESP_LOGI(CONN_TAG, "APP传图：跳转到Update界面");
                            if (lvgl_port_lock(100)) {
                                _ui_screen_change(&ui_ScreenUpdate, LV_SCR_LOAD_ANIM_NONE, 0, 0, &ui_ScreenUpdate_screen_init);
                                lvgl_port_unlock();
                            }
                            key_nav_set_context(NAV_CTX_UPDATE);
                        }
                    }
                }else if(SendStatus.isSend){
                    uint8_t pkt_no = *value;
                    uint8_t isEnd = *(value + 1);
                    // 每 100 包或最后一包打印日志（减少串口输出提升传输速度）
                    if (pkt_no % 100 == 0 || isEnd == 1) {
                        ESP_LOGI(CONN_TAG, "获取到数据：第:%d包,长度:%d,是否结束：%d", pkt_no+1, (int)param->write.len, isEnd);
                    }
                    uint8_t *data = value + 2;
                    // 防止缓冲区溢出：限制拷贝长度不超过预期大小
                    size_t copy_len = (size_t)param->write.len - 2;
                    if (SendStatus.port + copy_len > firstMeg.len) {
                        copy_len = firstMeg.len - SendStatus.port;
                    }
                    memcpy(img_data + SendStatus.port, data, copy_len);
                    SendStatus.port += copy_len;
                    if(isEnd == 1){
                        ESP_LOGI(CONN_TAG,"数据接收完毕，累计:%d字节，预期:%d字节，首字节:%02X %02X",
                            (int)SendStatus.port,(int)firstMeg.len,img_data[0],img_data[1]);
                        // 用实际接收长度写入文件（防止写入未初始化数据）
                        size_t received_len = SendStatus.port;
                        fwrite(img_data, sizeof(uint8_t), received_len, file_img);
                        fclose(file_img);
                        SendStatus.isSend = false;
                        SendStatus.port = 0;
                        // img_data 不释放，传给显示任务直通显示（跳过 SPIFFS 重读）
                        ble_pending_data = img_data;
                        ble_pending_data_size = received_len;
                        img_data = NULL;  // 转移所有权
                        free(filepath);
                        ESP_LOGI(CONN_TAG,"图片接收成功，数据直通显示(%d字节)", (int)ble_pending_data_size);
                        strncpy(ble_pending_filename, firstMeg.filename, sizeof(ble_pending_filename) - 1);
                        ble_pending_filename[sizeof(ble_pending_filename) - 1] = '\0';
                        xTaskNotifyGive(ble_process_task_handle);

                        // 通知传输模块接收完成（设备间传输模式时）
                        ble_transfer_on_receive_complete();
                    }
                }
            }// 图片编辑特征写入事件
            else if(param->write.handle == image_edit_handle){
                uint8_t *value = param->write.value;
                char imgName[23];
                uint8_t type = *(value + param->write.len - 1);
                memcpy(imgName, value, 23);
                if(type == 0xff){
                    // 耗时操作转移到独立任务执行
                    strncpy(ble_pending_filename, imgName, sizeof(ble_pending_filename) - 1);
                    ble_pending_filename[sizeof(ble_pending_filename) - 1] = '\0';
                    xTaskNotifyGive(ble_process_task_handle);
                }else if(type == 0xF1){
                    remove(filepath);
                    SendStatus.isSend = false;
                    SendStatus.port = 0;
                    free(img_data);
                    free(filepath);
                }
            }
            break;
        case ESP_GATTS_CONNECT_EVT:
            esp_ble_conn_update_params_t conn_params = {0};
            memcpy(conn_params.bda, param->connect.remote_bda, sizeof(esp_bd_addr_t));
            conn_params.latency = 0;
            conn_params.max_int = 16;   // 16 × 1.25ms = 20ms（缩短连接间隔提升传输吞吐量）
            conn_params.min_int = 6;    // 6 × 1.25ms = 7.5ms
            conn_params.timeout = 400;
            conn_id =  param->connect.conn_id;
            ESP_LOGI(CONN_TAG, "Connected, conn_id %u, remote "ESP_BD_ADDR_STR"",
                    param->connect.conn_id, ESP_BD_ADDR_HEX(param->connect.remote_bda));
            esp_ble_gap_update_conn_params(&conn_params);
            // 请求 2M PHY 提升传输速度（对端不支持时自动回退 1M，不影响兼容性）
            esp_ble_gap_set_preferred_phy(param->connect.remote_bda,
                ESP_BLE_GAP_NO_PREFER_TRANSMIT_PHY | ESP_BLE_GAP_NO_PREFER_RECEIVE_PHY,
                ESP_BLE_GAP_PHY_2M_PREF_MASK,
                ESP_BLE_GAP_PHY_2M_PREF_MASK,
                ESP_BLE_GAP_PHY_OPTIONS_NO_PREF);
            break;
        case ESP_GATTS_DISCONNECT_EVT:
            ESP_LOGI(CONN_TAG, "Disconnected, remote "ESP_BD_ADDR_STR", reason 0x%02x",
            ESP_BD_ADDR_HEX(param->disconnect.remote_bda), param->disconnect.reason);
            // 清理未完成的传输，防止内存泄漏
            if (SendStatus.isSend) {
                ESP_LOGW(CONN_TAG, "传输中断，已接收 %d/%d 字节",
                    (int)SendStatus.port, (int)firstMeg.len);
                SendStatus.isSend = false;
                SendStatus.port = 0;
                if (img_data) { free(img_data); img_data = NULL; }
                if (filepath) { free(filepath); filepath = NULL; }
                if (file_img) { fclose(file_img); file_img = NULL; }
            }
            // 断连后仅在广播启用时重新广播
            if (ble_advertising_enabled) {
                esp_ble_gap_start_advertising(&adv_params);
            }
            break;
        default:
            break;
    }
}

// === BLE广播启停控制 ===

void ble_start(void)
{
    ble_advertising_enabled = true;
    esp_ble_gap_start_advertising(&adv_params);
    ESP_LOGI(CONN_TAG, "BLE广播已启动");
}

void ble_stop(void)
{
    ble_advertising_enabled = false;
    esp_ble_gap_stop_advertising();
    ESP_LOGI(CONN_TAG, "BLE广播已停止");
}

bool ble_is_active(void)
{
    return ble_advertising_enabled;
}
