#include "weather_api.h"
#include <string>
#include <unordered_map>
#include <cctype>
#include <vector>
#include <time.h>

// ESP32 ESP-IDF headers
#ifdef __cplusplus
extern "C" {
#endif
#include "esp_http_client.h"
#include "esp_log.h"
#include "cJSON.h"
#include "esp_crt_bundle.h"
#include "esp_wifi.h"
#include "nvs.h"
#include "nvs_flash.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#ifdef __cplusplus
}
#endif
#include "zlib.h"

static const char* TAG = "WeatherApi";

// 天气代码映射表 - 将和风天气API的天气代码转换为中文描述
std::unordered_map<std::string, std::string> WeatherApi::WEATHER_CODE_MAP = {
    {"100", "晴"}, {"101", "多云"}, {"102", "少云"}, {"103", "晴间多云"},
    {"104", "阴"}, {"150", "晴"}, {"151", "多云"}, {"152", "少云"},
    {"153", "晴间多云"}, {"300", "阵雨"}, {"301", "强阵雨"}, {"302", "雷阵雨"},
    {"303", "强雷阵雨"}, {"304", "雷阵雨伴有冰雹"}, {"305", "小雨"}, {"306", "中雨"},
    {"307", "大雨"}, {"308", "极端降雨"}, {"309", "毛毛雨/细雨"}, {"310", "暴雨"},
    {"311", "大暴雨"}, {"312", "特大暴雨"}, {"313", "冻雨"}, {"314", "小到中雨"},
    {"315", "中到大雨"}, {"316", "大到暴雨"}, {"317", "暴雨到大暴雨"}, {"318", "大暴雨到特大暴雨"},
    {"350", "阵雨"}, {"351", "强阵雨"}, {"399", "雨"}, {"400", "小雪"},
    {"401", "中雪"}, {"402", "大雪"}, {"403", "暴雪"}, {"404", "雨夹雪"},
    {"405", "雨雪天气"}, {"406", "阵雨夹雪"}, {"407", "阵雪"}, {"408", "小到中雪"},
    {"409", "中到大雪"}, {"410", "大到暴雪"}, {"456", "阵雨夹雪"}, {"457", "阵雪"},
    {"499", "雪"}, {"500", "薄雾"}, {"501", "雾"}, {"502", "霾"},
    {"503", "扬沙"}, {"504", "浮尘"}, {"507", "沙尘暴"}, {"508", "强沙尘暴"},
    {"509", "浓雾"}, {"510", "强浓雾"}, {"511", "中度霾"}, {"512", "重度霾"},
    {"513", "严重霾"}, {"514", "大雾"}, {"515", "特强浓雾"}, {"900", "热"},
    {"901", "冷"}, {"999", "未知"}
};

static std::string MapLangCode(const std::string& lang) {
    if (lang.empty()) return "zh";
    if (lang == "zh_CN" || lang == "zh" || lang == "zh-Hans") return "zh";
    if (lang == "zh_HK" || lang == "zh-TW" || lang == "zh-Hant") return "zh-Hant";
    if (lang == "en_US" || lang == "en") return "en";
    if (lang == "ja_JP" || lang == "ja") return "ja";
    if (lang == "ko_KR" || lang == "ko") return "ko";
    if (lang == "fr_FR" || lang == "fr") return "fr";
    if (lang == "de_DE" || lang == "de") return "de";
    if (lang == "es_ES" || lang == "es") return "es";
    return "zh";
}

static bool IsGzipData(const std::string& data) {
    if (data.size() < 2) return false;
    const unsigned char* p = reinterpret_cast<const unsigned char*>(data.data());
    return p[0] == 0x1F && p[1] == 0x8B;
}

static bool GzipDecompress(const std::string& in, std::string& out) {
    if (in.empty()) return false;
    z_stream strm;
    memset(&strm, 0, sizeof(strm));
    strm.next_in = (Bytef*)in.data();
    strm.avail_in = (uInt)in.size();
    int ret = inflateInit2(&strm, 16 + MAX_WBITS);
    if (ret != Z_OK) {
        ESP_LOGE(TAG, "inflateInit2失败: %d", ret);
        return false;
    }
    std::vector<char> buf(1024);
    while (true) {
        strm.next_out = (Bytef*)buf.data();
        strm.avail_out = (uInt)buf.size();
        ret = inflate(&strm, Z_NO_FLUSH);
        if (ret == Z_STREAM_END) {
            size_t produced = buf.size() - strm.avail_out;
            if (produced) out.append(buf.data(), produced);
            break;
        } else if (ret == Z_OK || ret == Z_BUF_ERROR) {
            size_t produced = buf.size() - strm.avail_out;
            if (produced) out.append(buf.data(), produced);
            continue;
        } else {
            ESP_LOGE(TAG, "inflate失败: %d", ret);
            inflateEnd(&strm);
            return false;
        }
    }
    inflateEnd(&strm);
    return true;
}

// 缓存条目结构体，包含时间戳信息
typedef struct {
    time_t timestamp;// 缓存条目时间戳
} CacheEntry;

// 缓存上限常量
#define MAX_WIFI_CITY_CACHE 5

// WeatherApi构造函数，初始化配置参数
WeatherApi::WeatherApi() {
    // 硬编码配置参数 - 从get_weather.py文件中提取的配置，与小智server保持一致
    api_host_ = "kq3aapg9h5.re.qweatherapi.com";
    api_key_ = "aa5ec0859c144ac7b33966e25eef5580";
    default_location_ = "北京"; // 默认城市设置为北京
    kid_ = "T45F5GTR8Y";
    project_id_ = "4N855TEVNN";
    private_key_ = "-----BEGIN PRIVATE KEY-----\nMC4CAQAwBQYDK2VwBCIEIA26lz31HoaZV17EjIGcyo9YNGGQ77/gOZU8Chw8wlWq\n-----END PRIVATE KEY-----";
    
    ESP_LOGI(TAG, "初始化天气API配置 - 默认城市: %s", default_location_.c_str());
    ESP_LOGI(TAG, "WiFi位置缓存限制已设置为: %d 条", MAX_WIFI_CITY_CACHE);
}

// 生成JWT令牌（预留接口，当前版本暂不实现完整JWT认证）
std::string WeatherApi::GenerateJwtToken() {
    ESP_LOGI(TAG, "JWT令牌生成预留接口");
    return "";
}

// 封装HTTP GET请求
bool WeatherApi::HttpGet(const std::string& url, const std::string& headers, std::string& response) {
    ESP_LOGI(TAG, "HTTP请求: %s", url.c_str());
    
    esp_http_client_config_t config = {};
    config.url = url.c_str();
    config.method = HTTP_METHOD_GET;
    config.transport_type = HTTP_TRANSPORT_OVER_SSL;
#ifdef CONFIG_MBEDTLS_CERTIFICATE_BUNDLE
    config.crt_bundle_attach = esp_crt_bundle_attach;
#else
    ESP_LOGE(TAG, "证书包未启用，无法进行服务器证书验证。请在 menuconfig 启用 ESP-TLS Certificate Bundle");
#endif
    
    esp_http_client_handle_t client = esp_http_client_init(&config);
    if (!client) {
        ESP_LOGE(TAG, "HTTP客户端初始化失败");
        return false;
    }
    
    if (!headers.empty()) {
        esp_http_client_set_header(client, "Authorization", headers.c_str());
    }
    
    esp_http_client_set_header(client, "User-Agent", 
        "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 "
        "(KHTML, like Gecko) Chrome/92.0.4515.107 Safari/537.36");
    esp_http_client_set_header(client, "Accept", "application/json");
    // esp_http_client_set_header(client, "Accept-Encoding", "identity");// 禁用压缩，防止解压失败
    
    esp_err_t err = esp_http_client_open(client, 0);
    bool success = false;
    
    if (err == ESP_OK) {
        int64_t headers_len = esp_http_client_fetch_headers(client);
        int status_code = esp_http_client_get_status_code(client);
        ESP_LOGI(TAG, "HTTP状态码: %d, 头长度: %lld", status_code, (long long)headers_len);
        if (status_code == 200) {
            char buf[512];
            int read_len;
            int total = 0;
            while ((read_len = esp_http_client_read(client, buf, sizeof(buf))) > 0) {
                response.append(buf, read_len);
                total += read_len;
            }
            if (IsGzipData(response)) {
                std::string decompressed;
                if (GzipDecompress(response, decompressed)) {
                    response.swap(decompressed);
                    ESP_LOGI(TAG, "GZIP解压成功，解压后长度: %d", (int)response.size());
                } else {
                    ESP_LOGE(TAG, "GZIP解压失败，保留原始响应");
                }
            }
            success = (total > 0);
            ESP_LOGI(TAG, "读取完成，累计长度: %d", total);
            if (!success) {
                ESP_LOGE(TAG, "读取响应内容失败");
            }
        } else {
            ESP_LOGE(TAG, "HTTP请求失败，状态码: %d", status_code);
        }
        esp_http_client_close(client);
    } else {
        ESP_LOGE(TAG, "HTTP请求执行失败: %s", esp_err_to_name(err));
    }
    
    esp_http_client_cleanup(client);
    
    vTaskDelay(100 / portTICK_PERIOD_MS);
    
    return success;
}

// URL编码函数
std::string UrlEncode(const std::string& str) {
    std::string encoded;
    for (char c : str) {
        if (isalnum(c) || c == '-' || c == '_' || c == '.' || c == '~') {
            encoded += c;
        } else {
            encoded += '%';
            encoded += "0123456789ABCDEF"[static_cast<unsigned char>(c) / 16];
            encoded += "0123456789ABCDEF"[static_cast<unsigned char>(c) % 16];
        }
    }
    return encoded;
}

// 获取城市信息
std::string WeatherApi::FetchCityInfo(const std::string& location, const std::string& lang) {
    ESP_LOGI(TAG, "[FetchCityInfo] 开始获取城市信息，location参数: '%s', 长度: %zu", location.c_str(), location.length());
    
    // 对location参数进行URL编码
    std::string encoded_location = UrlEncode(location);
    ESP_LOGI(TAG, "[FetchCityInfo] URL编码后: '%s'", encoded_location.c_str());
    
    // 构建城市信息查询URL
    std::string q_lang = MapLangCode(lang);
    std::string url = "https://" + api_host_ + "/geo/v2/city/lookup?key=" + api_key_ + 
                     "\u0026location=" + encoded_location + "\u0026lang=" + q_lang;
    std::string response;
    
    ESP_LOGI(TAG, "[FetchCityInfo] API主机: '%s', API密钥长度: %zu", api_host_.c_str(), api_key_.length());
    ESP_LOGI(TAG, "[FetchCityInfo] 查询城市信息URL: '%s'", url.c_str());
    
    // 发送HTTP请求
    ESP_LOGI(TAG, "[FetchCityInfo] 开始发送HTTP GET请求");
    if (HttpGet(url, "", response)) {
        ESP_LOGI(TAG, "[FetchCityInfo] HTTP请求成功，响应长度: %zu 字节", response.length());
        ESP_LOGD(TAG, "[FetchCityInfo] 响应内容前100字节: '%s'", response.substr(0, std::min(size_t(100), response.length())).c_str());
        
        // 解析JSON响应
        cJSON* root = cJSON_Parse(response.c_str());
        if (root) {
            ESP_LOGI(TAG, "[FetchCityInfo] JSON解析成功");
            
            // 检查响应状态
            cJSON* code = cJSON_GetObjectItem(root, "code");
            if (code) {
                ESP_LOGI(TAG, "[FetchCityInfo] 响应状态码存在: '%s'", code->valuestring);
                if (cJSON_IsString(code) && strcmp(code->valuestring, "200") == 0) {
                    ESP_LOGI(TAG, "[FetchCityInfo] 响应状态码为200，成功");
                    
                    // 获取location数组
                    cJSON* location_array = cJSON_GetObjectItem(root, "location");
                    if (location_array) {
                        ESP_LOGI(TAG, "[FetchCityInfo] location数组存在");
                        if (cJSON_IsArray(location_array)) {
                            int array_size = cJSON_GetArraySize(location_array);
                            ESP_LOGI(TAG, "[FetchCityInfo] location数组大小: %d", array_size);
                            
                            if (array_size > 0) {
                                // 获取第一个城市信息
                                cJSON* first_location = cJSON_GetArrayItem(location_array, 0);
                                if (first_location) {
                                    ESP_LOGI(TAG, "[FetchCityInfo] 获取到第一个城市信息对象");
                                    
                                    // 获取城市ID
                                    cJSON* id = cJSON_GetObjectItem(first_location, "id");
                                    if (id) {
                                        ESP_LOGI(TAG, "[FetchCityInfo] 城市ID字段存在");
                                        if (cJSON_IsString(id)) {
                                            std::string city_id = id->valuestring;
                                            ESP_LOGI(TAG, "[FetchCityInfo] 成功获取城市ID: '%s'", city_id.c_str());
                                            cJSON_Delete(root);
                                            return city_id;
                                        } else {
                                            ESP_LOGE(TAG, "[FetchCityInfo] 城市ID不是字符串类型");
                                        }
                                    } else {
                                        ESP_LOGE(TAG, "[FetchCityInfo] 未能获取城市ID字段");
                                    }
                                } else {
                                    ESP_LOGE(TAG, "[FetchCityInfo] 未能获取第一个城市信息对象");
                                }
                            } else {
                                ESP_LOGE(TAG, "[FetchCityInfo] location数组为空");
                            }
                        } else {
                            ESP_LOGE(TAG, "[FetchCityInfo] location不是数组类型");
                        }
                    } else {
                        ESP_LOGE(TAG, "[FetchCityInfo] 响应中没有location数组");
                    }
                } else {
                    ESP_LOGE(TAG, "[FetchCityInfo] 城市信息API返回错误码: '%s'", code->valuestring);
                }
            } else {
                ESP_LOGE(TAG, "[FetchCityInfo] 响应中没有code字段");
            }
            cJSON_Delete(root);
        } else {
            ESP_LOGE(TAG, "[FetchCityInfo] 解析城市信息JSON失败");
            ESP_LOGD(TAG, "[FetchCityInfo] 失败的JSON响应: '%s'", response.c_str());
        }
    } else {
        ESP_LOGE(TAG, "[FetchCityInfo] HTTP请求失败");
    }
    
    ESP_LOGI(TAG, "[FetchCityInfo] 函数结束，返回空字符串");
    return "";
}

// 解析并打印IP位置信息- IP查询
static bool ParseAndPrintIpInfo(const std::string& response) {
    ESP_LOGI(TAG, "开始解析IP位置信息JSON");
    
    // 解析JSON响应
    cJSON* root = cJSON_Parse(response.c_str());
    if (!root) {
        const char* error_ptr = cJSON_GetErrorPtr();
        ESP_LOGE(TAG, "解析IP信息JSON失败: %s", error_ptr ? error_ptr : "未知错误");
        return false;
    }
    
    // 提取并打印各个字段（ip-api.com 格式）
    cJSON* status = cJSON_GetObjectItem(root, "status");
    cJSON* ip = cJSON_GetObjectItem(root, "query");
    cJSON* country = cJSON_GetObjectItem(root, "country");
    cJSON* region = cJSON_GetObjectItem(root, "region");
    cJSON* regionName = cJSON_GetObjectItem(root, "regionName");
    cJSON* city = cJSON_GetObjectItem(root, "city");
    cJSON* zip = cJSON_GetObjectItem(root, "zip");
    cJSON* lat = cJSON_GetObjectItem(root, "lat");
    cJSON* lon = cJSON_GetObjectItem(root, "lon");
    cJSON* timezone = cJSON_GetObjectItem(root, "timezone");
    cJSON* isp = cJSON_GetObjectItem(root, "isp");
    cJSON* org = cJSON_GetObjectItem(root, "org");
    cJSON* asn = cJSON_GetObjectItem(root, "as");
    
    // 打印解析结果
    ESP_LOGI(TAG, "=============== IP位置信息 ===============");
    if (status && cJSON_IsString(status)) {
        ESP_LOGI(TAG, "状态: %s", status->valuestring);
    }
    if (ip && cJSON_IsString(ip)) {
        ESP_LOGI(TAG, "IP: %s", ip->valuestring);
    }
    if (country && cJSON_IsString(country)) {
        ESP_LOGI(TAG, "国家: %s", country->valuestring);
    }
    if (region && cJSON_IsString(region)) {
        ESP_LOGI(TAG, "区域代码: %s", region->valuestring);
    }
    if (regionName && cJSON_IsString(regionName)) {
        ESP_LOGI(TAG, "省份: %s", regionName->valuestring);
    }
    if (city && cJSON_IsString(city)) {
        ESP_LOGI(TAG, "城市: %s", city->valuestring);
    }
    if (zip && cJSON_IsString(zip)) {
        ESP_LOGI(TAG, "邮编: %s", zip->valuestring);
    }
    if (lat && cJSON_IsNumber(lat)) {
        ESP_LOGI(TAG, "纬度: %.4f", lat->valuedouble);
    }
    if (lon && cJSON_IsNumber(lon)) {
        ESP_LOGI(TAG, "经度: %.4f", lon->valuedouble);
    }
    if (timezone && cJSON_IsString(timezone)) {
        ESP_LOGI(TAG, "时区: %s", timezone->valuestring);
    }
    if (isp && cJSON_IsString(isp)) {
        ESP_LOGI(TAG, "运营商: %s", isp->valuestring);
    }
    if (org && cJSON_IsString(org)) {
        ESP_LOGI(TAG, "组织: %s", org->valuestring);
    }
    if (asn && cJSON_IsString(asn)) {
        ESP_LOGI(TAG, "AS号: %s", asn->valuestring);
    }
    ESP_LOGI(TAG, "======================================");
    
    // 释放JSON对象
    cJSON_Delete(root);
    return true;
}

// 获取IP位置信息（ip-api.com）
// 自动获取设备当前IP的地理位置信息
std::string WeatherApi::GetIpInfo() {
    ESP_LOGI(TAG, "[GetIpInfo] 开始获取IP位置信息");
    
    // 构建IP查询API的URL
    std::string url = "http://ip-api.com/json/?lang=zh-CN";
    ESP_LOGI(TAG, "[GetIpInfo] 查询URL: %s", url.c_str());
    std::string response;
    std::string city_info = default_location_; // 默认返回默认位置
    
    // 使用HTTP
    esp_http_client_config_t config = {};
    config.url = url.c_str();
    config.method = HTTP_METHOD_GET;
    config.transport_type = HTTP_TRANSPORT_OVER_TCP; // 使用HTTP而非HTTPS
    
    esp_http_client_handle_t client = esp_http_client_init(&config);
    if (!client) {
        ESP_LOGE(TAG, "[GetIpInfo] HTTP客户端初始化失败");
        return city_info;
    }
    
    // 设置请求头
    esp_http_client_set_header(client, "User-Agent", 
        "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 "
        "(KHTML, like Gecko) Chrome/92.0.4515.107 Safari/537.36");
    
    esp_http_client_set_header(client, "Accept-Encoding", "identity");
    esp_err_t err = esp_http_client_open(client, 0);
    if (err == ESP_OK) {
        int64_t headers_len = esp_http_client_fetch_headers(client);
        int status_code = esp_http_client_get_status_code(client);
        ESP_LOGI(TAG, "[GetIpInfo] HTTP状态码: %d, 头长度: %lld", status_code, (long long)headers_len);
        if (status_code == 200) {
            char buf[512];
            int read_len;
            while ((read_len = esp_http_client_read(client, buf, sizeof(buf))) > 0) {
                response.append(buf, read_len);
            }
            
            ESP_LOGI(TAG, "[GetIpInfo] 获取到响应，长度: %zu 字节", response.length());
            
            if (ParseAndPrintIpInfo(response)) {
                cJSON* root = cJSON_Parse(response.c_str());
                if (root) {
                    cJSON* city = cJSON_GetObjectItem(root, "city");
                    cJSON* regionName = cJSON_GetObjectItem(root, "regionName");
                    if (city && cJSON_IsString(city) && city->valuestring[0] != '\0') {
                        city_info = city->valuestring;
                    } else if (regionName && cJSON_IsString(regionName)) {
                        city_info = regionName->valuestring;
                    }
                    cJSON_Delete(root);
                }
            }
        } else {
            ESP_LOGE(TAG, "[GetIpInfo] HTTP请求失败，状态码: %d", status_code);
        }
        
        esp_http_client_close(client);// 关闭HTTP客户端连接，释放资源
    } else {
        ESP_LOGE(TAG, "[GetIpInfo] HTTP请求执行失败: %s", esp_err_to_name(err));
    }
    
    esp_http_client_cleanup(client);// 清理HTTP客户端资源，释放内存
    vTaskDelay(100 / portTICK_PERIOD_MS);// 延时100ms，确保资源释放完成
    
    ESP_LOGI(TAG, "[GetIpInfo] 返回城市信息: %s", city_info.c_str());
    return city_info;// 返回提取的城市信息
}

// 获取天气信息主函数
std::string WeatherApi::GetWeather(const std::string& location, const std::string& lang) {
    ESP_LOGI(TAG, "[GetWeather] ===== 开始获取天气信息 =====");
    ESP_LOGI(TAG, "[GetWeather] 输入参数: location='%s' (长度: %zu), lang='%s'", 
             location.c_str(), location.length(), lang.c_str());
    
    // 确定查询位置 - 当location为空或为"None"字符串时，使用默认城市
    std::string query_location = (location.empty() || location == "None") ? default_location_ : location;
    ESP_LOGI(TAG, "[GetWeather] 查询位置: '%s'", query_location.c_str());
    
    // 检查缓存 - 简单的内存缓存
    std::string cache_key = "weather_" + query_location;
    ESP_LOGI(TAG, "[GetWeather] 缓存键: '%s'", cache_key.c_str());
    
    auto it = weather_cache_.find(cache_key);
    if (it != weather_cache_.end()) {
        ESP_LOGI(TAG, "[GetWeather] 使用缓存的天气信息: '%s'", query_location.c_str());
        ESP_LOGI(TAG, "[GetWeather] ===== 天气信息获取完成 (缓存命中) =====");
        return it->second; // 返回缓存的结果
    }
    
    ESP_LOGI(TAG, "[GetWeather] 缓存未命中，开始获取天气信息: '%s'", query_location.c_str());
    
    // 获取城市ID
    ESP_LOGI(TAG, "[GetWeather] 开始获取城市ID");
    std::string city_id = FetchCityInfo(query_location, lang);
    ESP_LOGI(TAG, "[GetWeather] FetchCityInfo返回结果: city_id='%s' (长度: %zu)", 
             city_id.c_str(), city_id.length());
    
    if (city_id.empty()) {
        ESP_LOGI(TAG, "[GetWeather] 未找到相关城市信息，请确认城市名称是否正确");
        ESP_LOGI(TAG, "[GetWeather] ===== 天气信息获取失败 (城市ID为空) =====");
        return "未找到相关城市信息，请确认城市名称是否正确";
    }
    
    std::string q_lang = MapLangCode(lang);// 映射语言代码为API需要的格式
    std::string weather_url = "https://" + api_host_ + "/v7/weather/now?key=" + api_key_ + "\u0026location=" + city_id + "\u0026lang=" + q_lang;
    std::string weather_response;// 存储天气API响应的字符串
    
    ESP_LOGI(TAG, "[GetWeather] 构建天气查询URL: '%s'", weather_url.c_str());
    std::string result = "";// 存储最终格式化的天气信息
    
    // 发送天气查询请求
    ESP_LOGI(TAG, "[GetWeather] 开始发送天气查询HTTP请求");
    if (HttpGet(weather_url, "", weather_response)) {
        ESP_LOGI(TAG, "[GetWeather] HTTP请求成功，响应长度: %zu 字节", weather_response.length());
        
        // 解析天气JSON响应
        ESP_LOGI(TAG, "[GetWeather] 开始解析天气JSON响应");
        cJSON* root = cJSON_Parse(weather_response.c_str());
        if (root) {
            ESP_LOGI(TAG, "[GetWeather] JSON解析成功");
            
            // 检查响应状态
            cJSON* code = cJSON_GetObjectItem(root, "code");
            if (code && cJSON_IsString(code) && strcmp(code->valuestring, "200") == 0) {
                ESP_LOGI(TAG, "[GetWeather] 响应状态码: 200 (成功)");
                
                // 获取天气数据
                cJSON* now = cJSON_GetObjectItem(root, "now");
                if (now) {
                    ESP_LOGI(TAG, "[GetWeather] 获取到now字段，开始构建天气报告");
                    
                    // 构建天气报告
                    result = "前天气情况 (" + query_location + ")\n\n";
                    
                    // 获取天气描述
                    cJSON* text = cJSON_GetObjectItem(now, "text");
                    if (text && cJSON_IsString(text)) {
                        result += "天气状况: " + std::string(text->valuestring) + "\n";
                        ESP_LOGI(TAG, "[GetWeather] 天气状况: '%s'", text->valuestring);
                    } else {
                        ESP_LOGW(TAG, "[GetWeather] 未能获取天气状况");
                    }
                    
                    // 获取温度
                    cJSON* temp = cJSON_GetObjectItem(now, "temp");
                    if (temp && cJSON_IsString(temp)) {
                        result += "当前温度: " + std::string(temp->valuestring) + "摄氏度\n";
                        ESP_LOGI(TAG, "[GetWeather] 当前温度: '%s'摄氏度", temp->valuestring);
                    } else {
                        ESP_LOGW(TAG, "[GetWeather] 未能获取当前温度");
                    }
                    
                    // 获取体感温度
                    cJSON* feelsLike = cJSON_GetObjectItem(now, "feelsLike");
                    if (feelsLike && cJSON_IsString(feelsLike)) {
                        result += "体感温度: " + std::string(feelsLike->valuestring) + "摄氏度\n";
                        ESP_LOGI(TAG, "[GetWeather] 体感温度: '%s'摄氏度", feelsLike->valuestring);
                    } else {
                        ESP_LOGW(TAG, "[GetWeather] 未能获取体感温度");
                    }
                    
                    // 获取风向风速
                    cJSON* windDir = cJSON_GetObjectItem(now, "windDir");
                    cJSON* windScale = cJSON_GetObjectItem(now, "windScale");
                    if (windDir && cJSON_IsString(windDir) && windScale && cJSON_IsString(windScale)) {
                        result += "风向风速: " + std::string(windDir->valuestring) + " " + 
                                  std::string(windScale->valuestring) + "级\n";
                        ESP_LOGI(TAG, "[GetWeather] 风向风速: '%s' %s级", windDir->valuestring, windScale->valuestring);
                    } else {
                        ESP_LOGW(TAG, "[GetWeather] 未能获取风向风速信息");
                    }
                    
                    // 获取湿度
                    cJSON* humidity = cJSON_GetObjectItem(now, "humidity");
                    if (humidity && cJSON_IsString(humidity)) {
                        result += "相对湿度: " + std::string(humidity->valuestring) + "%\n";
                        ESP_LOGI(TAG, "[GetWeather] 相对湿度: '%s'%%", humidity->valuestring);
                    } else {
                        ESP_LOGW(TAG, "[GetWeather] 未能获取相对湿度");
                    }
                    
                    // 获取气压
                    cJSON* pressure = cJSON_GetObjectItem(now, "pressure");
                    if (pressure && cJSON_IsString(pressure)) {
                        result += "大气压强: " + std::string(pressure->valuestring) + "hPa\n";
                        ESP_LOGI(TAG, "[GetWeather] 大气压强: '%s'hPa", pressure->valuestring);
                    } else {
                        ESP_LOGW(TAG, "[GetWeather] 未能获取大气压强");
                    }
                    
                    // 添加更新时间
                    result += std::string("\n数据更新时间: ") + __DATE__ + " " + __TIME__;
                    ESP_LOGI(TAG, "[GetWeather] 数据更新时间: %s %s", __DATE__, __TIME__);
                    
                } else {
                    ESP_LOGE(TAG, "[GetWeather] 无法获取当前天气数据(now字段为空)");
                    result = "无法获取当前天气数据";
                }
            } else {
                const char* error_code = code && cJSON_IsString(code) ? code->valuestring : "未知";
                ESP_LOGE(TAG, "[GetWeather] 天气API请求失败，错误码: '%s'", error_code);
                result = "天气API请求失败，错误码: " + std::string(error_code);
            }
            cJSON_Delete(root);
        } else {
            ESP_LOGE(TAG, "[GetWeather] 解析天气数据失败，请稍后重试");
            result = "解析天气数据失败，请稍后重试";
        }
    } else {
        ESP_LOGE(TAG, "[GetWeather] 网络请求失败，无法获取天气信息");
        result = "网络请求失败，无法获取天气信息";
    }
    
    // 缓存结果 - 简单实现，实际项目中应考虑缓存过期时间
    if (!result.empty()) {
        ESP_LOGI(TAG, "[GetWeather] 开始缓存天气结果，当前缓存大小: %zu", weather_cache_.size());
        weather_cache_[cache_key] = result;
        
        // 限制缓存大小
        if (weather_cache_.size() > 10) {
            ESP_LOGI(TAG, "[GetWeather] 缓存大小超过10，移除最旧的缓存项");
            weather_cache_.erase(weather_cache_.begin());
        }
        ESP_LOGI(TAG, "[GetWeather] 缓存完成，当前缓存大小: %zu", weather_cache_.size());
    }
    
    ESP_LOGI(TAG, "[GetWeather] 天气信息获取完成");
    ESP_LOGI(TAG, "[GetWeather] ===== 天气信息获取流程结束 =====");
    return result;
}

// 创建全局WeatherApi实例
WeatherApi g_weather_api;

// 实现全局GetWeatherInfo函数，用于获取天气信息// 全局函数，供外部调用
std::string GetWeatherInfo(const std::string& location, const std::string& lang) {
    ESP_LOGI(TAG, "[GetWeatherInfo] ===== 全局函数调用开始 =====");
    ESP_LOGI(TAG, "[GetWeatherInfo] 收到调用请求，location='%s' (长度: %zu), lang='%s'",location.c_str(), location.length(), lang.c_str());
    
    // 调用g_weather_api单例的GetWeather方法
    ESP_LOGI(TAG, "[GetWeatherInfo] 准备调用g_weather_api.GetWeather");
    std::string result = g_weather_api.GetWeather(location, lang);// 调用单例实例的GetWeather方法获取天气信息
    
    ESP_LOGI(TAG, "[GetWeatherInfo] g_weather_api.GetWeather调用完成，结果长度: %zu 字节", result.length());
    ESP_LOGD(TAG, "[GetWeatherInfo] 返回结果前100字节: '%s'", result.substr(0, std::min(size_t(100), result.length())).c_str());
    ESP_LOGI(TAG, "[GetWeatherInfo] ===== 全局函数调用结束 =====");
    return result;
}

std::string WeatherApi::GetDefaultLocation() const {
    return default_location_;// 返回默认位置
}

// 新增方法：自动检测NVS中是否存在当前位置的城市信息，并设置当前位置
void WeatherApi::AutoDetectLocation() {
    ESP_LOGI(TAG, "[AutoDetectLocation] ===== 开始自动检测位置 =====");
    wifi_config_t wc{};// 定义WiFi配置结构体
    esp_wifi_get_config(WIFI_IF_STA, &wc);// 获取当前WiFi配置
    std::string ssid = std::string(reinterpret_cast<char*>(wc.sta.ssid));// 转换SSID为字符串
    wifi_ap_record_t ap{};// 定义AP记录结构体
    std::string bssid;// 定义BSSID字符串
    if (esp_wifi_sta_get_ap_info(&ap) == ESP_OK) {
        char buf[18];// 定义BSSID缓冲区
        snprintf(buf, sizeof(buf), "%02x:%02x:%02x:%02x:%02x:%02x",
                 ap.bssid[0], ap.bssid[1], ap.bssid[2],
                 ap.bssid[3], ap.bssid[4], ap.bssid[5]);// 格式化BSSID为字符串
        bssid.assign(buf);// 赋值给BSSID字符串
    }
    nvs_handle_t h;// 定义NVS句柄
    // 打开NVS命名空间"wifi_city_map"，读写模式
    if (nvs_open("wifi_city_map", NVS_READWRITE, &h) == ESP_OK) {
        auto try_get = [&](const std::string& key)->std::string{
            size_t len = 0;
            // 尝试获取NVS中存储的城市字符串
            if (nvs_get_str(h, key.c_str(), NULL, &len) == ESP_OK && len > 0) {
                std::vector<char> buf(len);// 定义缓冲区
                // 尝试从NVS获取城市字符串
                if (nvs_get_str(h, key.c_str(), buf.data(), &len) == ESP_OK) {
                    return std::string(buf.data());// 返回城市字符串
                }
            }
            return std::string();// 未找到对应城市，返回空字符串
        };
        std::string city;// 定义城市字符串
        if (!ssid.empty()) {
            if (!bssid.empty()) {
                city = try_get(ssid + "|" + bssid);// 先尝试SSID+BSSID
            }
            if (city.empty()) {
                city = try_get(ssid);// 如果未找到，再尝试SSID
            }
        }
        // 如果仍未从NVS中找到城市信息，将调用位置API获取城市信息
        if (city.empty()) {
            ESP_LOGI(TAG, "[AutoDetectLocation] 未从NVS命中城市信息，将调用位置API获取城市信息");
            std::string detected = GetIpInfo();// 获取IP位置信息 调用位置查询API获取当前位置的城市信息
            if (!detected.empty()) {
                default_location_ = detected;// 更新默认城市为检测到的位置
                if (!ssid.empty()) {
                    size_t cache_count = 0;// 初始化缓存条目数量
                    std::vector<std::string> cache_entries;      // 定义缓存条目向量，存储所有键
                    std::vector<std::string> deletable_entries;  // 存储可删除的条目（排除当前使用的SSID和SSID+BSSID）
                    
                    // 遍历NVS中的所有键
                    nvs_iterator_t it = NULL;
                    esp_err_t res = nvs_entry_find(NULL, "wifi_city_map", NVS_TYPE_STR, &it);// 查找所有字符串类型的条目
                    while (res == ESP_OK) {
                        nvs_entry_info_t info;    // 定义NVS条目信息结构体
                        nvs_entry_info(it, &info);// 获取当前迭代器指向的条目信息
                        
                        std::string key = info.key;  // 获取当前条目的键名
                        cache_entries.push_back(key);// 将键添加到缓存向量中
                        cache_count++;// 增加缓存条目数量
                        
                        // 检查是否为当前使用的键，如果不是则添加到可删除列表
                        std::string current_full_key = ssid;
                        if (!bssid.empty()) {current_full_key = ssid + "|" + bssid;}// 组合SSID和BSSID作为完整键
                        
                        // 排除当前正在使用的SSID和SSID+BSSID键
                        if (key != ssid && key != current_full_key) {deletable_entries.push_back(key);}// 将键添加到可删除列表
                        res = nvs_entry_next(&it);// 移动到下一个条目
                    }
                    nvs_release_iterator(it);// 释放NVS迭代器
                    
                    // 如果缓存数量超过限制且有可删除的条目，随机删除一个
                    if (cache_count >= MAX_WIFI_CITY_CACHE && !deletable_entries.empty()) {
                        ESP_LOGI(TAG, "[AutoDetectLocation] WiFi位置缓存数量(%zu)达到限制(%d)，开始随机删除策略",cache_count, MAX_WIFI_CITY_CACHE);
                        
                        // 随机选择一个条目删除（使用更简单的方式选择索引）,ESP32平台可以使用esp_random()获得更好的随机性，但这里保持简单实现
                        int random_index = (int)(esp_timer_get_time() % deletable_entries.size());// 生成随机索引
                        const std::string& key_to_delete = deletable_entries[random_index];// 获取随机选择的键名
                        ESP_LOGI(TAG, "[AutoDetectLocation] 随机删除缓存条目: %s", key_to_delete.c_str());
                        nvs_erase_key(h, key_to_delete.c_str());// 删除城市字符串键
                    }
                    
                    // 保存新的位置信息
                    if (!bssid.empty()) {
                        const std::string full_key = ssid + "|" + bssid;// 组合SSID和BSSID作为完整键
                        nvs_set_str(h, full_key.c_str(), detected.c_str());// 缓存SSID+BSSID到城市
                    }
                    nvs_set_str(h, ssid.c_str(), detected.c_str());// 缓存SSID到城市
                    
                    if (nvs_commit(h) == ESP_OK) {
                        ESP_LOGI(TAG, "[AutoDetectLocation] 城市信息保存到NVS成功！");
                    } else {
                        ESP_LOGW(TAG, "[AutoDetectLocation] 城市信息保存到NVS失败！");
                    }
                }
                ESP_LOGI(TAG, "[AutoDetectLocation] 自动检测到位置: '%s'，已更新默认城市", detected.c_str());
            } else {
                ESP_LOGI(TAG, "[AutoDetectLocation] 位置检测失败或未变化，保持默认城市: '%s'", default_location_.c_str());
            }
        } 
        // 如果从NVS命中城市，找到了城市信息
        else {
            default_location_ = city;// 更新默认城市为NVS中命中的城市
            ESP_LOGI(TAG, "[AutoDetectLocation] 从NVS命中位置: '%s'，已更新默认城市", city.c_str());
        }
        nvs_close(h);// 关闭NVS句柄
    } 
    // 如果打开NVS检索城市信息失败
    else {
        std::string detected = GetIpInfo();// 调用位置API获取城市信息
        if (!detected.empty()) {
            default_location_ = detected;// 更新默认城市为检测到的位置
            ESP_LOGI(TAG, "[AutoDetectLocation] 自动检测到位置: '%s'，已更新默认城市", detected.c_str());
        } else {
            ESP_LOGI(TAG, "[AutoDetectLocation] 位置检测失败或未变化，保持默认城市: '%s'", default_location_.c_str());
        }
    }
    ESP_LOGI(TAG, "[AutoDetectLocation] ===== 位置检测完成 =====");
}

// 全局函数：供应用程序网络连接后调用，用于自动检测位置
void AutoDetectAndSetLocation() {
    ESP_LOGI(TAG, "[AutoDetectAndSetLocation] 调用全局函数自动检测位置");
    g_weather_api.AutoDetectLocation();// 自动检测NVS中是否存在当前位置的城市信息，并设置当前位置
}
