// 设备间蓝牙图片传输模块
// 发送方：GATT Client 扫描→发现→连接→MTU协商→发现服务→分包写入
// 接收方：复用现有 GATT Server（IMAGE_WRITE 0x0B01），协议完全兼容
// 不影响现有 APP 传图：APP 通过 KEY2 单击（Peiwang），设备间通过 KEY2 长按/双击

#include "ble_transfer.h"
#include "ble.h"
#include "pages.h"
#include "key_nav.h"
#include "esp_log.h"
#include "esp_bt.h"
#include "esp_gap_ble_api.h"
#include "esp_gattc_api.h"
#include "esp_bt_main.h"
#include "esp_gatt_common_api.h"
#include "esp_lvgl_port.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "ui/ui.h"
#include "ui/screens/ui_ScreenImg.h"
#include "ui/screens/ui_ScreenSharing.h"
#include "ui/screens/ui_ScreenReceiving.h"
#include <string.h>
#include <stdio.h>

static const char *TAG = "BLE_XFER";

// === 状态管理 ===
static ble_xfer_state_t xfer_state = BLE_XFER_IDLE;
static bool receiving_mode = false;  // 接收方模式标识

// === GATT Client 相关 ===
#define XFER_APP_ID         1      // 与现有Server的APP_ID=0区分
#define IMAGE_SERVICE_UUID  0x0B00
#define IMAGE_WRITE_UUID    0x0B01

static esp_gatt_if_t client_gattc_if = ESP_GATT_IF_NONE;
static uint16_t client_conn_id = 0;
static uint16_t client_write_handle = 0;
static esp_bd_addr_t target_bda;           // 扫描到的目标设备地址
static bool target_found = false;
static uint16_t client_mtu = 23;           // 协商后的MTU值

// === 发送任务相关 ===
static TaskHandle_t send_task_handle = NULL;
static volatile bool send_cancel_flag = false;
static volatile bool gattc_congested = false;  // BLE链路拥塞标志

// === 扫描参数 ===
static esp_ble_scan_params_t scan_params = {
    .scan_type = BLE_SCAN_TYPE_ACTIVE,
    .own_addr_type = BLE_ADDR_TYPE_PUBLIC,
    .scan_filter_policy = BLE_SCAN_FILTER_ALLOW_ALL,
    .scan_interval = 0x50,    // 50ms
    .scan_window = 0x30,      // 30ms
    .scan_duplicate = BLE_SCAN_DUPLICATE_DISABLE,
};

// === 前向声明 ===
static void gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if, esp_ble_gattc_cb_param_t *param);
static void send_image_task(void *arg);

// === 接口实现 ===

ble_xfer_state_t ble_transfer_get_state(void) {
    return xfer_state;
}

bool ble_transfer_is_receiving(void) {
    return receiving_mode;
}

void ble_transfer_init(void) {
    // 注册 GATT Client 回调
    esp_err_t ret = esp_ble_gattc_register_callback(gattc_event_handler);
    if (ret) {
        ESP_LOGE(TAG, "GATTC回调注册失败: %s", esp_err_to_name(ret));
        return;
    }
    // 注册 GATT Client 应用
    ret = esp_ble_gattc_app_register(XFER_APP_ID);
    if (ret) {
        ESP_LOGE(TAG, "GATTC应用注册失败: %s", esp_err_to_name(ret));
        return;
    }
    ESP_LOGI(TAG, "设备间传输模块初始化完成");
}

void ble_transfer_start_send(void) {
    if (xfer_state != BLE_XFER_IDLE) {
        ESP_LOGW(TAG, "传输正在进行中，忽略");
        return;
    }

    // 如果当前正在为APP广播，先停止
    if (ble_is_active()) {
        ble_stop();
    }

    xfer_state = BLE_XFER_SCANNING;
    target_found = false;
    send_cancel_flag = false;

    // 开始扫描（扫描5秒）
    esp_ble_gap_set_scan_params(&scan_params);
    ESP_LOGI(TAG, "发送方：开始扫描接收设备...");
}

void ble_transfer_start_receive(void) {
    if (xfer_state != BLE_XFER_IDLE) {
        ESP_LOGW(TAG, "传输正在进行中，忽略");
        return;
    }

    receiving_mode = true;
    xfer_state = BLE_XFER_RECEIVING;

    // 启动广播（复用现有GATT Server）
    ble_start();
    ESP_LOGI(TAG, "接收方：已开始广播，等待发送设备连接...");
}

void ble_transfer_cancel(void) {
    ESP_LOGI(TAG, "取消传输，当前状态: %d", xfer_state);

    send_cancel_flag = true;

    switch (xfer_state) {
        case BLE_XFER_SCANNING:
            esp_ble_gap_stop_scanning();
            break;
        case BLE_XFER_CONNECTING:
        case BLE_XFER_SENDING:
            if (client_conn_id != 0) {
                esp_ble_gattc_close(client_gattc_if, client_conn_id);
            }
            break;
        case BLE_XFER_RECEIVING:
            ble_stop();
            receiving_mode = false;
            break;
        default:
            break;
    }

    xfer_state = BLE_XFER_IDLE;
}

// === GAP 扫描结果回调（由 ble.c 的 esp_gap_cb 转发） ===
// 在 ble.c 中增加对扫描事件的转发

void ble_transfer_handle_scan_result(void *param) {
    if (xfer_state != BLE_XFER_SCANNING) return;

    esp_ble_gap_cb_param_t *scan_result = (esp_ble_gap_cb_param_t *)param;
    switch (scan_result->scan_rst.search_evt) {
        case ESP_GAP_SEARCH_INQ_RES_EVT: {
            // 检查广播数据 + Scan Response 中是否包含服务UUID 0x0B00
            // ESP-IDF 的 ble_adv 缓冲区中 ADV 数据和 Scan Response 数据连续存放
            uint8_t *adv_data = scan_result->scan_rst.ble_adv;
            uint8_t adv_len = scan_result->scan_rst.adv_data_len
                            + scan_result->scan_rst.scan_rsp_len;

            // 解析广播数据，查找 0x0B00 服务UUID
            uint8_t *p = adv_data;
            while (p < adv_data + adv_len) {
                uint8_t field_len = p[0];
                if (field_len == 0) break;
                uint8_t field_type = p[1];

                // 检查 Scan Response 中的完整16位服务UUID列表
                if (field_type == ESP_BLE_AD_TYPE_16SRV_CMPL ||
                    field_type == ESP_BLE_AD_TYPE_16SRV_PART) {
                    for (int i = 2; i < field_len + 1; i += 2) {
                        uint16_t uuid16 = p[i] | (p[i + 1] << 8);
                        if (uuid16 == IMAGE_SERVICE_UUID) {
                            // 找到目标设备！
                            memcpy(target_bda, scan_result->scan_rst.bda, sizeof(esp_bd_addr_t));
                            target_found = true;
                            ESP_LOGI(TAG, "发现接收设备: "ESP_BD_ADDR_STR,
                                     ESP_BD_ADDR_HEX(target_bda));

                            // 停止扫描，准备连接
                            esp_ble_gap_stop_scanning();
                            return;
                        }
                    }
                }

                // 检查厂商数据中的"LDdzbj"标识
                if (field_type == ESP_BLE_AD_MANUFACTURER_SPECIFIC_TYPE && field_len >= 7) {
                    if (memcmp(p + 2, "\x4C\x44\x64\x7A\x62\x6A", 6) == 0) {
                        memcpy(target_bda, scan_result->scan_rst.bda, sizeof(esp_bd_addr_t));
                        target_found = true;
                        ESP_LOGI(TAG, "发现接收设备(厂商标识): "ESP_BD_ADDR_STR,
                                 ESP_BD_ADDR_HEX(target_bda));
                        esp_ble_gap_stop_scanning();
                        return;
                    }
                }

                p += field_len + 1;
            }
            break;
        }
        case ESP_GAP_SEARCH_INQ_CMPL_EVT:
            // 扫描完成
            if (!target_found) {
                ESP_LOGW(TAG, "扫描完成，未发现接收设备，保持分享界面等待用户操作");
                // 不自动切换界面，保持ImageShar界面，等用户按键退出回Home
                xfer_state = BLE_XFER_IDLE;
            }
            break;
        default:
            break;
    }
}

void ble_transfer_handle_scan_stop(void) {
    if (xfer_state != BLE_XFER_SCANNING) return;

    if (target_found) {
        // 扫描停止成功，开始连接
        xfer_state = BLE_XFER_CONNECTING;
        esp_ble_gattc_open(client_gattc_if, target_bda, BLE_ADDR_TYPE_PUBLIC, true);
        ESP_LOGI(TAG, "正在连接目标设备...");
    }
}

// === GATT Client 事件处理 ===

static void gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if, esp_ble_gattc_cb_param_t *param) {
    switch (event) {
        case ESP_GATTC_REG_EVT:
            if (param->reg.status == ESP_GATT_OK) {
                client_gattc_if = gattc_if;
                ESP_LOGI(TAG, "GATTC注册成功, if=%d", gattc_if);
            } else {
                ESP_LOGE(TAG, "GATTC注册失败, status=%d", param->reg.status);
            }
            break;

        case ESP_GATTC_OPEN_EVT:
            if (param->open.status != ESP_GATT_OK) {
                ESP_LOGE(TAG, "连接失败, status=%d", param->open.status);
                xfer_state = BLE_XFER_FAILED;
                xfer_state = BLE_XFER_IDLE;
                return;
            }
            client_conn_id = param->open.conn_id;
            ESP_LOGI(TAG, "已连接, conn_id=%d", client_conn_id);

            // 协商MTU为512以加速传输
            esp_ble_gattc_send_mtu_req(gattc_if, client_conn_id);
            break;

        case ESP_GATTC_CFG_MTU_EVT:
            client_mtu = param->cfg_mtu.mtu;
            ESP_LOGI(TAG, "MTU协商完成: %d", client_mtu);
            // 开始发现服务
            esp_ble_gattc_search_service(gattc_if, client_conn_id, NULL);
            break;

        case ESP_GATTC_SEARCH_RES_EVT: {
            // 找到服务
            if (param->search_res.srvc_id.uuid.len == ESP_UUID_LEN_16 &&
                param->search_res.srvc_id.uuid.uuid.uuid16 == IMAGE_SERVICE_UUID) {
                ESP_LOGI(TAG, "发现图片传输服务, start_handle=%d, end_handle=%d",
                         param->search_res.start_handle, param->search_res.end_handle);

                // 获取特征值
                uint16_t count = 0;
                esp_gatt_status_t status = esp_ble_gattc_get_attr_count(
                    gattc_if, client_conn_id, ESP_GATT_DB_CHARACTERISTIC,
                    param->search_res.start_handle, param->search_res.end_handle, 0, &count);
                if (status == ESP_GATT_OK && count > 0) {
                    esp_gattc_char_elem_t *char_elems = malloc(sizeof(esp_gattc_char_elem_t) * count);
                    if (char_elems) {
                        status = esp_ble_gattc_get_all_char(
                            gattc_if, client_conn_id,
                            param->search_res.start_handle,
                            param->search_res.end_handle,
                            char_elems, &count, 0);
                        if (status == ESP_GATT_OK) {
                            for (int i = 0; i < count; i++) {
                                if (char_elems[i].uuid.len == ESP_UUID_LEN_16 &&
                                    char_elems[i].uuid.uuid.uuid16 == IMAGE_WRITE_UUID) {
                                    client_write_handle = char_elems[i].char_handle;
                                    ESP_LOGI(TAG, "发现IMAGE_WRITE特征, handle=%d", client_write_handle);
                                }
                            }
                        }
                        free(char_elems);
                    }
                }
            }
            break;
        }

        case ESP_GATTC_SEARCH_CMPL_EVT:
            if (client_write_handle == 0) {
                ESP_LOGE(TAG, "未找到IMAGE_WRITE特征");
                esp_ble_gattc_close(gattc_if, client_conn_id);
                xfer_state = BLE_XFER_IDLE;
                return;
            }

            // 切换到传输中界面
            xfer_state = BLE_XFER_SENDING;
            if (lvgl_port_lock(100)) {
                _ui_screen_change(&ui_ScreenSharing, LV_SCR_LOAD_ANIM_NONE, 0, 0, &ui_ScreenSharing_screen_init);
                lvgl_port_unlock();
            }
            key_nav_set_context(NAV_CTX_SHARING);

            // 启动发送任务
            xTaskCreate(send_image_task, "ble_send", 8192, NULL, 5, &send_task_handle);
            break;

        case ESP_GATTC_WRITE_CHAR_EVT:
            if (param->write.status != ESP_GATT_OK) {
                ESP_LOGE(TAG, "写入失败, handle=%d, status=%d",
                         param->write.handle, param->write.status);
            }
            break;

        case ESP_GATTC_CONGEST_EVT:
            // BLE链路拥塞状态变化：congested=true表示拥塞，false表示恢复
            gattc_congested = param->congest.congested;
            if (gattc_congested) {
                ESP_LOGW(TAG, "BLE链路拥塞，暂停发送");
            } else {
                ESP_LOGI(TAG, "BLE链路恢复，继续发送");
            }
            break;

        case ESP_GATTC_CLOSE_EVT:
        case ESP_GATTC_DISCONNECT_EVT:
            ESP_LOGI(TAG, "GATTC断开连接");
            client_conn_id = 0;
            client_write_handle = 0;
            gattc_congested = false;
            break;

        default:
            break;
    }
}

// === 图片发送任务 ===

static void send_image_task(void *arg) {
    ESP_LOGI(TAG, "开始发送图片...");

    // 获取当前显示的图片文件名
    const char *img_name = get_current_image();
    if (!img_name) {
        ESP_LOGE(TAG, "没有可发送的图片");
        goto send_fail;
    }

    // 打开图片文件
    char filepath[48];
    snprintf(filepath, sizeof(filepath), "/spiflash/%s", img_name);
    FILE *f = fopen(filepath, "rb");
    if (!f) {
        ESP_LOGE(TAG, "无法打开图片: %s", filepath);
        goto send_fail;
    }

    // 获取文件大小
    fseek(f, 0, SEEK_END);
    long file_size = ftell(f);
    fseek(f, 0, SEEK_SET);
    ESP_LOGI(TAG, "图片: %s, 大小: %ld 字节", img_name, file_size);

    // === 发送前序数据包 ===
    // 格式: [0xFD] [filename 22B] [size 3B big-endian] = 26 bytes
    uint8_t header[26];
    header[0] = 0xFD;
    memset(header + 1, 0, 22);
    strncpy((char *)(header + 1), img_name, 22);
    header[23] = (file_size >> 16) & 0xFF;
    header[24] = (file_size >> 8) & 0xFF;
    header[25] = file_size & 0xFF;

    // 使用 Write Without Response（与APP一致），不等待ACK，靠固定延时流控
    esp_err_t ret = esp_ble_gattc_write_char(client_gattc_if, client_conn_id,
        client_write_handle, sizeof(header), header,
        ESP_GATT_WRITE_TYPE_NO_RSP, ESP_GATT_AUTH_REQ_NONE);
    if (ret != ESP_OK) {
        ESP_LOGE(TAG, "前序包写入失败: %s", esp_err_to_name(ret));
        fclose(f);
        goto send_fail;
    }
    vTaskDelay(pdMS_TO_TICKS(50));  // 等待对端建立接收缓冲区（与APP一致）

    // === 分包发送图片数据 ===
    // 格式: [pkt_no 1B] [isEnd 1B] [data ...]
    // ATT Write Command 最大 value = MTU - 3（ATT头），减去2字节包头(pkt_no+isEnd)
    int max_write_len = client_mtu - 3;
    if (max_write_len > 509) max_write_len = 509;
    int payload_size = max_write_len - 2;
    ESP_LOGI(TAG, "MTU=%d, 每包最大数据=%d字节", client_mtu, payload_size);

    uint8_t pkt_buf[512];
    int pkt_no = 0;
    size_t total_sent = 0;
    gattc_congested = false;

    while (total_sent < file_size) {
        if (send_cancel_flag) {
            ESP_LOGW(TAG, "发送被取消");
            fclose(f);
            goto send_fail;
        }

        // 拥塞等待：BLE TX 缓冲区满时暂停，等待 CONGEST_EVT 通知恢复
        int congest_wait = 0;
        while (gattc_congested && congest_wait < 500) {
            vTaskDelay(pdMS_TO_TICKS(10));
            congest_wait += 10;
        }
        if (congest_wait >= 500) {
            ESP_LOGE(TAG, "拥塞超时，传输中止");
            fclose(f);
            goto send_fail;
        }

        size_t remaining = file_size - total_sent;
        size_t chunk = (remaining > payload_size) ? payload_size : remaining;
        bool is_last = (total_sent + chunk >= file_size);

        pkt_buf[0] = (uint8_t)(pkt_no & 0xFF);
        pkt_buf[1] = is_last ? 1 : 0;
        size_t read_len = fread(pkt_buf + 2, 1, chunk, f);
        if (read_len != chunk) {
            ESP_LOGE(TAG, "文件读取错误");
            fclose(f);
            goto send_fail;
        }

        ret = esp_ble_gattc_write_char(client_gattc_if, client_conn_id,
            client_write_handle, read_len + 2, pkt_buf,
            ESP_GATT_WRITE_TYPE_NO_RSP, ESP_GATT_AUTH_REQ_NONE);
        if (ret != ESP_OK) {
            // API层面失败，递增延时重试
            int attempt = 0;
            while (ret != ESP_OK && attempt < 5) {
                attempt++;
                vTaskDelay(pdMS_TO_TICKS(20 * attempt));
                ret = esp_ble_gattc_write_char(client_gattc_if, client_conn_id,
                    client_write_handle, read_len + 2, pkt_buf,
                    ESP_GATT_WRITE_TYPE_NO_RSP, ESP_GATT_AUTH_REQ_NONE);
            }
            if (ret != ESP_OK) {
                ESP_LOGE(TAG, "写入失败（重试耗尽）: %s", esp_err_to_name(ret));
                fclose(f);
                goto send_fail;
            }
        }

        total_sent += chunk;
        pkt_no++;

        // 每包间隔：ESP32间需要比手机更长的间隔（手机BLE控制器TX缓冲更大）
        vTaskDelay(pdMS_TO_TICKS(20));

        if (pkt_no % 50 == 0) {
            ESP_LOGI(TAG, "已发送 %d/%ld 字节 (%d%%)",
                     (int)total_sent, file_size, (int)(total_sent * 100 / file_size));
        }
    }

    fclose(f);
    ESP_LOGI(TAG, "图片发送完成！共 %d 包，%ld 字节", pkt_no, file_size);

    // 等待对端处理完成（保存文件、刷新UI）
    vTaskDelay(pdMS_TO_TICKS(500));

    // 断开连接并关闭蓝牙节省资源
    ESP_LOGI(TAG, "发送完成：断开连接，关闭蓝牙");
    esp_ble_gattc_close(client_gattc_if, client_conn_id);
    ble_stop();

    // 传输成功，跳转到Img界面
    xfer_state = BLE_XFER_DONE;
    if (lvgl_port_lock(100)) {
        _ui_screen_change(&ui_ScreenImg, LV_SCR_LOAD_ANIM_NONE, 0, 0, &ui_ScreenImg_screen_init);
        lvgl_port_unlock();
    }
    key_nav_set_context(NAV_CTX_IMG);
    xfer_state = BLE_XFER_IDLE;

    send_task_handle = NULL;
    vTaskDelete(NULL);
    return;

send_fail:
    xfer_state = BLE_XFER_FAILED;
    ESP_LOGW(TAG, "发送失败：断开连接，关闭蓝牙");
    esp_ble_gattc_close(client_gattc_if, client_conn_id);
    ble_stop();
    if (lvgl_port_lock(100)) {
        _ui_screen_change(&ui_ScreenImg, LV_SCR_LOAD_ANIM_NONE, 0, 0, &ui_ScreenImg_screen_init);
        lvgl_port_unlock();
    }
    key_nav_set_context(NAV_CTX_IMG);
    xfer_state = BLE_XFER_IDLE;

    send_task_handle = NULL;
    vTaskDelete(NULL);
}

// === 接收完成回调（由 ble.c 的 GATTS 写入完成时调用） ===

void ble_transfer_on_receive_complete(void) {
    if (!receiving_mode) return;

    ESP_LOGI(TAG, "接收方：图片接收完成");
    receiving_mode = false;
    ble_stop();  // 停止广播

    // ble.c 中的 ble_process_task 已经处理了图片保存和导航到 ScreenImg
    // 这里只需更新传输状态和导航上下文
    xfer_state = BLE_XFER_DONE;
    key_nav_set_context(NAV_CTX_IMG);
    xfer_state = BLE_XFER_IDLE;
}
