#include "mqttconf_commun.h"
#include "wifidevnum_config.h"
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdint.h>

#include "freertos/FreeRTOS.h"
#include "freertos/task.h"

#include "esp_http_client.h"
#include "mqtt_client.h"
#include "esp_crt_bundle.h"
#include "esp_log.h"
#include "esp_netif.h"
#include "driver/gpio.h"
#include "cJSON.h"
#include "sdkconfig.h"
#include "esp_heap_caps.h"
#include "esp_ota_ops.h"
#include "esp_app_format.h"

#include "rc_pwm_control.h"
#include "betteryread.h"
#include "ota.h"
#include "remote_control.h"
#include "heart_payload.h"
#include "task_manager.h"

static const char *tag_s = "MQTT_MGR";
#define DEFAULT_MQTT_HOST "119.45.167.177" 

// 最多支持同时连接的服务器数量
#define MAX_MQTT_CLIENTS 10

typedef struct http_response_s {
    char *buffer; 
    int len;      
} http_response_t;

char g_device_id[32] = {0};       
static char g_sta_ip[16] = "0.0.0.0";    

// 存储所有活跃的 MQTT 客户端句柄，用于心跳群发
static esp_mqtt_client_handle_t client_list[MAX_MQTT_CLIENTS] = {NULL};
static int client_count = 0;
static TaskHandle_t g_hb_task = NULL;
static volatile bool g_hb_task_running = false;

static int mqttabnormal_exit_count = 0;

int mqtt_send_deviceota_info(void);

/**
 * @brief 构造心跳包内容
 */
static char* generate_hb_payload(void)
{
    return heart_payload_json_malloc(g_device_id, g_sta_ip, true);
}

static void mqtt_heartbeat_send_once(void) {
    char *json = generate_hb_payload();
    if (!json) return;

    //for (int i = 0; i < client_count; i++) {
        //if (client_list[i] != NULL) {
             if (strlen(g_device_id) == 0) {
                esp_mqtt_client_publish(client_list[0], "000000000", json, 0, 1, 0);
                esp_mqtt_client_publish(client_list[0], "dev2app/000000000", json, 0, 1, 0);
                free(json);
                return;
             }
            // 向每个服务器发送心跳，确保 App 在每个 Broker 都能看到设备在线
            esp_mqtt_client_publish(client_list[0], g_device_id, json, 0, 1, 0);
            char t2[64];
            snprintf(t2, sizeof(t2), "dev2app/%s", g_device_id);
            esp_mqtt_client_publish(client_list[0], t2, json, 0, 1, 0);
    //    }
    //}
    free(json);
}

static void mqtt_heartbeat_task(void *arg)
{
    (void)arg;
    while (g_hb_task_running) {
        vTaskDelay(pdMS_TO_TICKS(3000));
        if (!g_hb_task_running) {
            break;
        }
        mqtt_heartbeat_send_once();
    }
    vTaskDelete(NULL);
}

// 定时器句柄
TimerHandle_t ota_msg_timer;

// 定时器触发后的回调函数
void ota_msg_send_task(void *pvParameters) {
    // 将传入的参数转回延迟秒数
    int delay_seconds = (int)(intptr_t)pvParameters;

    // 在任务内部进行延迟，不阻塞其他程序
    vTaskDelay(pdMS_TO_TICKS(delay_seconds * 1000));
    

    ESP_LOGI("OTA_TASK", "延迟结束，正在发送 MQTT OTA 信息...");
    
    // 执行你的 MQTT 发送逻辑
    mqtt_send_deviceota_info();

    // 2. 关键：发送完毕后，任务自行销毁，实现“自动取消”和内存释放
    ESP_LOGI("OTA_TASK", "发送完成，任务已自动退出并销毁");
    vTaskDelete(NULL); 
}

/**
 * @brief 启动延迟发送
 * @param delay_seconds 延迟几秒发送
 */
void start_ota_report_timer(int delay_seconds) {
    ESP_LOGI("OTA_TASK", "创建一次性任务，将在 %d 秒后执行", delay_seconds);

    (void)app_task_start(APP_TASK_MQTT_OTA_REPORT, ota_msg_send_task, (void *)(intptr_t)delay_seconds, NULL);
}

/**
 * @brief MQTT 事件回调
 */
static void common_mqtt_event_handler(void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data) {
    esp_mqtt_event_handle_t event = event_data;
    const char *ip = (const char *)handler_args;

    switch (event->event_id) {
        case MQTT_EVENT_CONNECTED:
            ESP_LOGI(tag_s, "[%s] 已连接", ip);
            if(strcmp(ip,DEFAULT_MQTT_HOST)==0){
                start_ota_report_timer(5);
            }
            char s1[64], s2[64];
            snprintf(s1, sizeof(s1), "app2dev/%s", g_device_id);
            snprintf(s2, sizeof(s2), "ser2dev/%s", g_device_id);
            esp_mqtt_client_subscribe(event->client, s1, 1);
            esp_mqtt_client_subscribe(event->client, s2, 1);
            break;

        case MQTT_EVENT_DATA:
            if (event->data_len > 0) {
                char *tmp = malloc(event->data_len + 1);
                if (tmp) {
                    mqttabnormal_exit_count = 0;
                    memcpy(tmp, event->data, event->data_len);
                    tmp[event->data_len] = '\0';
                    remote_control_apply_json(tmp);

                    free(tmp);
                }
            }
            break;

        case MQTT_EVENT_DISCONNECTED:
            ESP_LOGW(tag_s, "[%s] 连接断开", ip);
            break;

        case MQTT_EVENT_ERROR:
            ESP_LOGE(tag_s, "[%s] 发生错误", ip);
            break;
            
        default: break;
    }
}

/**
 * @brief 初始化并启动一个 MQTT 客户端
 */
static void start_mqtt_client(const char *ip) {
    if (!ip || client_count >= MAX_MQTT_CLIENTS) return;

    char *persist_ip = strdup(ip);
    char uri[128];
    snprintf(uri, sizeof(uri), "mqtt://%s:1883", persist_ip);
    ESP_LOGI(tag_s, "启动并发连接: %s", uri);

    esp_mqtt_client_config_t mqtt_cfg = {
        .broker.address.uri = uri,
        .credentials.username = "admin",
        .credentials.authentication.password = "admin",
        .session.keepalive = 60,
        .network.timeout_ms = 20000,
        .buffer.size = 2048,
        .task.stack_size = 6144,
    };

    esp_mqtt_client_handle_t client = esp_mqtt_client_init(&mqtt_cfg);
    if (client) {
        esp_mqtt_client_register_event(client, ESP_EVENT_ANY_ID, common_mqtt_event_handler, (void*)persist_ip);
        esp_mqtt_client_start(client);
        client_list[client_count++] = client; // 加入心跳群发列表
    }
}

esp_err_t _http_event_handler(esp_http_client_event_t *evt) {
    http_response_t *response = (http_response_t *)evt->user_data;
    if (evt->event_id == HTTP_EVENT_ON_DATA) {
        char *new_buf = realloc(response->buffer, response->len + evt->data_len + 1);
        if (new_buf) {
            response->buffer = new_buf;
            memcpy(response->buffer + response->len, evt->data, evt->data_len);
            response->len += evt->data_len;
            response->buffer[response->len] = '\0';
        }
    }
    return ESP_OK;
}

/**
 * @brief 初始化任务：拉取列表并同时启动所有连接
 */
static void config_pull_and_init_task(void *pvParameters) {
    vTaskDelay(pdMS_TO_TICKS(5000)); 

    esp_netif_ip_info_t ip_info;
    esp_netif_t *netif = esp_netif_get_handle_from_ifkey("WIFI_STA_DEF");
    if (esp_netif_get_ip_info(netif, &ip_info) == ESP_OK) {
        esp_ip4addr_ntoa(&ip_info.ip, g_sta_ip, sizeof(g_sta_ip));
    }
    read_from_nvs(DEVICE_CFG_KEY_DEVICE_ID, g_device_id, sizeof(g_device_id)-1);
    rc_pwm_control_set_drive_from_device_id(g_device_id);

    if (strlen(g_device_id) == 0) {
        start_mqtt_client(DEFAULT_MQTT_HOST);
        goto start_timer;
    }

    char url[256];
    snprintf(url, sizeof(url), "%s%s", CONFIG_ROBOIOT_MQTT_URL, g_device_id);
    http_response_t resp = { .buffer = NULL, .len = 0 };
    esp_http_client_config_t http_cfg = {
        .url = url,
        .event_handler = _http_event_handler,
        .user_data = &resp,
        .crt_bundle_attach = esp_crt_bundle_attach,
        .timeout_ms = 8000,
    };
    esp_http_client_handle_t http_client = esp_http_client_init(&http_cfg);
    
    bool dynamic_ok = false;
    if (esp_http_client_perform(http_client) == ESP_OK && resp.buffer) {
        cJSON *root = cJSON_Parse(resp.buffer);
        if (root) {
            cJSON *data_node = cJSON_GetObjectItem(root, "data");
            if (data_node) {
                cJSON *mqtt_list = cJSON_GetObjectItem(data_node, "mqtt");
                if (cJSON_IsArray(mqtt_list)) {
                    dynamic_ok = true;
                    int sz = cJSON_GetArraySize(mqtt_list);
                    for (int i = 0; i < sz; i++) {
                        cJSON *item = cJSON_GetArrayItem(mqtt_list, i);
                        if (cJSON_IsString(item)) {
                            start_mqtt_client(item->valuestring); // 同时启动
                        }
                    }
                }
            }
            cJSON_Delete(root);
        }
    }
    if (resp.buffer) free(resp.buffer);
    esp_http_client_cleanup(http_client);

    if (!dynamic_ok) {
        start_mqtt_client(DEFAULT_MQTT_HOST);
    }

start_timer:
    // 统一心跳任务（每3秒群发一次），支持绑核
    if (g_hb_task == NULL) {
        g_hb_task_running = true;
        if (app_task_start(APP_TASK_MQTT_HEARTBEAT, mqtt_heartbeat_task, NULL, &g_hb_task) != ESP_OK) {
            g_hb_task_running = false;
            ESP_LOGE(tag_s, "heart task create failed");
        } else {
            ESP_LOGI(tag_s, "并发心跳群发任务已启动(core=auto)");
        }
    }
    
    vTaskDelete(NULL); 
}

// 新增停止函数
void mqtt_manager_stop(void) {
    ESP_LOGW(tag_s, "正在停止 MQTT 服务...");

    // 1. 停止心跳任务
    if (g_hb_task != NULL) {
        g_hb_task_running = false;
        app_task_stop(&g_hb_task);
    }

    // 2. 销毁所有 MQTT 客户端
    for (int i = 0; i < client_count; i++) {
        if (client_list[i] != NULL) {
            esp_mqtt_client_stop(client_list[i]);
            esp_mqtt_client_disconnect(client_list[i]);
            esp_mqtt_client_destroy(client_list[i]);
            client_list[i] = NULL;
        }
    }
    client_count = 0;
    
    ESP_LOGI(tag_s, "MQTT 服务已完全停止");
}


/**
 * @brief  发送设备信息到 MQTT（JSON 格式）
 * @return 0 成功，-1 失败
 */
int mqtt_send_deviceota_info(void)
{
    cJSON *root = NULL;
    char *json_str = NULL;
    int ret = -1;

    /* 1. 创建 JSON 对象 */
    root = cJSON_CreateObject();
    if (!root) {
        return -1;
    }

    /* 2. 添加字段（直接读取全局变量） */
    cJSON_AddStringToObject(root, "device_id", g_device_id);
    const esp_app_desc_t *app_desc = esp_app_get_description();
    const char* running_version = app_desc->version; 
    cJSON_AddStringToObject(root, "version", running_version);

    /* 3. JSON 转字符串（紧凑格式，适合 MQTT） */
    json_str = cJSON_PrintUnformatted(root);
    if (!json_str) {
        goto exit;
    }

    /* 4. MQTT 发送 */
    esp_mqtt_client_publish(client_list[0], "esp32updata",json_str, 0, 1, 0);

exit:
    if (json_str) {
        free(json_str);
    }
    if (root) {
        cJSON_Delete(root);
    }

    return ret;
}

/*
 * @brief MQTT 异常任务
*/
void mqtt_abnormal_exittask(void *pvParameters)
{
    vTaskDelay(pdMS_TO_TICKS(3000));
    ESP_LOGI(tag_s, "MQTT异常任务启动");
    while(1){
        if(client_list[0] == NULL) {
            vTaskDelay(pdMS_TO_TICKS(1000));
            continue;
        }
        
        if(mqttabnormal_exit_count>5){
            rc_vehicle_stop();
            mqttabnormal_exit_count=6;
        }
        mqttabnormal_exit_count++;
        vTaskDelay(pdMS_TO_TICKS(100));
    }

}

/* MQTT 异常任务初始化*/
void mqtt_abnormal_exittask_init(void) { 
    (void)app_task_start(APP_TASK_MQTT_EXIT, mqtt_abnormal_exittask, NULL, NULL);
}

/**
 * @brief MQTT 初始化任务
*/
void mqtt_manager_init_sequence(void) {
    (void)app_task_start(APP_TASK_MQTT_INIT, config_pull_and_init_task, NULL, NULL);
}