#include "ota.h"
#include "esp_log.h"
#include "esp_ota_ops.h"
#include "esp_app_format.h"
#include "esp_http_client.h"
#include "esp_https_ota.h"
#include "esp_crt_bundle.h"
#include "esp_system.h"
#include "nvs_flash.h"
#include "wifidevnum_config.h" // 假设你有封装好的 read_from_nvs 和 save_to_nvs
#include "esp_spiffs.h"
#include <cJSON.h>
#include <string.h>


static const char *tag_s = "OTA_UPDATE";

/**
 * @brief HTTP 事件处理
 */
esp_err_t _ota_http_event_handler(esp_http_client_event_t *evt) {
    switch (evt->event_id) {
        case HTTP_EVENT_ERROR: ESP_LOGE(tag_s, "HTTP_EVENT_ERROR"); break;
        case HTTP_EVENT_ON_CONNECTED: ESP_LOGI(tag_s, "已连接到服务器"); break;
        case HTTP_EVENT_ON_FINISH: ESP_LOGI(tag_s, "数据传输完成"); break;
        default: break;
    }
    return ESP_OK;
}

/**
 * @brief 启动 OTA
 */
void start_ota_update(const char* url) {
    ESP_LOGI(tag_s, "正在从 URL 启动 OTA: %s", url);

    esp_http_client_config_t config = {
        .url = url,
        .crt_bundle_attach = esp_crt_bundle_attach,
        .event_handler = _ota_http_event_handler,
        .keep_alive_enable = true,
        .timeout_ms = 10000,
    };

    esp_https_ota_config_t ota_config = {
        .http_config = &config,
    };

    ESP_LOGI(tag_s, "正在下载并写入固件... 请勿断电");
    esp_err_t ret = esp_https_ota(&ota_config);

       // 在这里获取更新后的分区指针
    const esp_partition_t *updated_partition = esp_ota_get_next_update_partition(NULL);
    if (ret == ESP_OK) {
        ESP_LOGI(tag_s, "OTA 升级成功！即将重启...");
        ESP_LOGI(tag_s, "找到更新分区: %s (偏移: 0x%08x)", 
                     updated_partition->label, updated_partition->address);

        esp_err_t set_err = esp_ota_set_boot_partition(updated_partition);
        if (set_err == ESP_OK) {
            ESP_LOGI(tag_s, "启动分区设置成功！");
            
            // 验证设置结果
            const esp_partition_t *boot_partition = esp_ota_get_boot_partition();
            const esp_partition_t *running_partition = esp_ota_get_running_partition();
            
            ESP_LOGI(tag_s, "当前运行分区: %s (0x%08x)", 
                        running_partition->label, running_partition->address);
            ESP_LOGI(tag_s, "下次启动分区: %s (0x%08x)", 
                        boot_partition->label, boot_partition->address);
            
            // 等待设置完成
            vTaskDelay(2000 / portTICK_PERIOD_MS);
            esp_restart();
        }else {
                ESP_LOGE(tag_s, "设置启动分区失败: %s", esp_err_to_name(set_err));
        }
        
    } else {
        ESP_LOGE(tag_s, "OTA 升级失败: %s", esp_err_to_name(ret));
    }
}


/**
 * @brief MQTT 消息处理函数：解析 JSON 并判断是否需要更新
 */
int ota_update_recmqtt(const char *json_data) { 
    if (json_data == NULL) return -1;

    cJSON *root = cJSON_Parse(json_data);
    if (root == NULL) return -1;

    ESP_LOGI(tag_s, "当前固件运行版本: %s", CONFIG_MY_APP_VERSION);

    // 2. 解析云端发来的新版本号
    cJSON *new_version_obj = cJSON_GetObjectItem(root, "new_version");
    if (!cJSON_IsString(new_version_obj) || (new_version_obj->valuestring == NULL)) {
        cJSON_Delete(root);
        return -1;
    }
    const char* cloud_version = new_version_obj->valuestring;

    // 3. 版本对比
    if (strcmp(CONFIG_MY_APP_VERSION, cloud_version) == 0) {
        ESP_LOGI(tag_s, "当前已是最新版本 (%s)，跳过更新。", CONFIG_MY_APP_VERSION);
        cJSON_Delete(root);
        return 0; 
    }

    ESP_LOGI(tag_s, "检测到新版本: %s -> %s",CONFIG_MY_APP_VERSION, cloud_version);

    // 5. 解析下载地址并启动更新
    cJSON *esp32_url = cJSON_GetObjectItem(root, "esp32_url");
    if (cJSON_IsString(esp32_url) && (esp32_url->valuestring != NULL)) {
        start_ota_update(esp32_url->valuestring);
    } else {
        ESP_LOGE(tag_s, "JSON 中未找到有效的 esp32_url");
    }

    cJSON_Delete(root);
    return 0;
}


