#include "wifi_board.h"
#include "audio_codecs/es8311_audio_codec.h"
#include "display/lcd_display.h"
#include "application.h"
#include "button.h"
#include "config.h"
#include "i2c_device.h"
#include "iot/thing_manager.h"
#include "../../components/gbk_encoding/include/gbk_encoding.h"  // 使用完整路径

#include <esp_log.h>
#include <esp_lcd_panel_vendor.h>
#include <driver/i2c_master.h>
#include <driver/spi_common.h>
#include <wifi_station.h>
#include "led/single_led.h"
#include "assets/lang_config.h"
#include "esp_lcd_panel_gc9301.h"

#include "power_save_timer.h"
#include "power_manager.h"
#include <driver/rtc_io.h>
#include <esp_sleep.h>

#include <string.h>
#include <sys/unistd.h>
#include <sys/stat.h>
#include "esp_vfs_fat.h"
#include "sdmmc_cmd.h"
#include "driver/sdmmc_host.h"
#include <dirent.h>
#include <nvs_flash.h>  // 添加NVS头文件
#include <nvs.h>        // 添加NVS头文件

#include "audio_player.h" // 音频播放器

#define TAG "JiuchuangDevBoard"
#define __USER_GPIO_PWRDOWN__

LV_FONT_DECLARE(font_puhui_20_4);
LV_FONT_DECLARE(font_awesome_20_4);
// 前向声明
class JiuchuangDevBoard;

// 音频播放器必须的回调函数
static esp_err_t audio_mute_callback(AUDIO_PLAYER_MUTE_SETTING setting);
static esp_err_t audio_clk_set_callback(uint32_t rate, uint32_t bits_cfg, i2s_slot_mode_t ch);
static esp_err_t audio_write_callback(void *audio_buffer, size_t len, size_t *bytes_written, uint32_t timeout_ms);
static void audio_event_callback(audio_player_cb_ctx_t *ctx);
static esp_err_t restore_device_status();
static void sd_card_detect_task(void *arg);
static bool is_supported_audio_file(const char *filename)
{
    int len = strlen(filename);
    if (len <= 4)
        return false;

    const char *ext = filename + len - 4;
    return (strcasecmp(ext, ".mp3") == 0 ||
            strcasecmp(ext, ".wav") == 0);
}

// 添加一个辅助函数用于将二进制数据转换成十六进制字符串，方便调试
static std::string bytes_to_hex(const uint8_t* data, size_t len) {
    std::string result;
    result.reserve(len * 3);
    for (size_t i = 0; i < len; i++) {
        char buf[4];
        snprintf(buf, sizeof(buf), "%02X ", data[i]);
        result += buf;
    }
    return result;
}

// 添加一个简单的GBK到UTF-8转换映射表，覆盖常用的中文字符
struct GbkUtf8Mapping {
    uint16_t gbk_code;
    const char *utf8_str;
};

// 常用的中文字符GBK到UTF-8的映射，扩充更多常用字符
static const GbkUtf8Mapping gbk_utf8_map[] = {
    // 您的音乐文件名中出现的字符
    {0xB6AA, "丢"}, {0xCAD6, "手"}, {0xBEEE, "绢"},  // 丢手绢
    {0xD0A1, "小"}, {0xCFBC, "霞"},                   // 小霞
    {0xD7F9, "座"}, {0xCEBB, "位"},                   // 座位
    {0xB8E6, "告"}, {0xB0D7, "白"}, {0xC6F8, "气"}, {0xC7F2, "球"}, // 告白气球
    {0xB0AE, "爱"}, {0xB4ED, "错"},                   // 爱错
    
    // 扩充更多常用汉字
    // 数字相关
    {0xD2BB, "一"}, {0xB6FE, "二"}, {0xC8FD, "三"}, {0xCBC4, "四"}, {0xCEE5, "五"},
    {0xC1F9, "六"}, {0xC6DF, "七"}, {0xB0CB, "八"}, {0xBEC5, "九"}, {0xCAE5, "十"},
    {0xB0D9, "百"}, {0xC7A7, "千"}, {0xCDF2, "万"}, {0xD2DA, "亿"},
    
    // 常用形容词
    {0xBAC3, "好"}, {0xBDD6, "快"}, {0xC2A5, "乐"}, {0xD0C2, "新"}, {0xC0CF, "老"},
    {0xD0A1, "小"}, {0xB4F3, "大"}, {0xB8DF, "高"}, {0xB5CD, "低"}, {0xD1D5, "颜"},
    {0xC9AB, "色"}, {0xBADA, "美"}, {0xB3C1, "沉"}, {0xCFE0, "箱"}, {0xB5E7, "电"},
    
    // 常用名词
    {0xC4EA, "年"}, {0xD4C2, "月"}, {0xC8D5, "日"}, {0xCEC4, "星"}, {0xC6DA, "期"},
    {0xCAB1, "时"}, {0xBFE4, "刻"}, {0xB7D6, "分"}, {0xC3EB, "秒"}, {0xC4DA, "内"},
    {0xBEA9, "京"}, {0xC9CF, "上"}, {0xBAA3, "海"}, {0xB9E3, "广"}, {0xD6DD, "州"},
    {0xC7ED, "青"}, {0xB5BA, "岛"}, {0xCED2, "我"}, {0xC4E3, "你"}, {0xCBFB, "他"},
    
    // 常用动词
    {0xBFB4, "看"}, {0xCFB7, "玩"}, {0xCFDF, "走"}, {0xD7F7, "做"}, {0xCEC2, "写"},
    {0xCBB5, "说"}, {0xCFD6, "想"}, {0xCFC2, "下"}, {0xC9CF, "上"}, {0xD7F8, "左"},
    {0xD3D2, "右"}, {0xC7B0, "前"}, {0xBBA7, "户"}, {0xCDE2, "外"}, {0xCBF7, "室"},
    
    // 音乐相关
    {0xD2F4, "音"}, {0xC0D6, "乐"}, {0xB8E8, "歌"}, {0xB3CC, "程"}, {0xB5C6, "灯"},
    {0xB9E2, "光"}, {0xCAD3, "视"}, {0xC6C1, "频"}, {0xBDA1, "舞"}, {0xC7FA, "曲"},
    {0xC4DA, "内"}, {0xCDA8, "涨"}, {0xBCA3, "汪"}, {0xB7D2, "佳"}, {0xBBAA, "华"},
    
    // 音乐人名
    {0xCEB2, "沈"}, {0xD6A3, "郑"}, {0xC9A1, "秀"}, {0xCEB0, "薛"}, {0xD6EC, "之"},
    {0xCFC9, "谦"}, {0xB8B7, "蔡"}, {0xD2AF, "依"}, {0xC1D5, "林"}, {0xD4AA, "元"},
    {0xBAA3, "海"}, {0xC0BC, "蓝"}, {0xDEB9, "魏"}, {0xB4EF, "敖"},
    
    // 常用标点符号
    {0xA3BA, "："}, {0xA3BB, "；"}, {0xA1A4, "。"}, {0xA3AC, "，"}, {0xA1A2, "、"},
    {0xA3BF, "？"}, {0xA3A1, "！"}, {0xA1B0, "—"}, {0xA1B1, "…"}, {0xA1F1, "·"},
    
    // 更多可能的中文字符映射可以根据需要添加
};

// 更优化的字符编码转换函数，连续检测和转换GBK编码
static std::string gbk_to_utf8(const char* gbk_str) {
    std::string utf8_result;
    const unsigned char* p = (const unsigned char*)gbk_str;
    
    while (*p) {
        if (*p < 0x80) {
            // ASCII字符，直接复制
            utf8_result += *p;
            p++;
        } else if (*p >= 0x81 && *p <= 0xFE && *(p+1) >= 0x40 && *(p+1) <= 0xFE) {
            // 可能是GBK编码的中文字符
            uint16_t gbk_code = (*p << 8) | *(p + 1);
            bool found = false;
            
            // 查找映射表
            for (const auto& mapping : gbk_utf8_map) {
                if (mapping.gbk_code == gbk_code) {
                    utf8_result += mapping.utf8_str;
                    found = true;
                    break;
                }
            }
            
            if (!found) {
                // 如果找不到映射，使用占位符并记录未识别的编码
                ESP_LOGW(TAG, "未识别的GBK编码: 0x%04X", gbk_code);
                utf8_result += "?";
            }
            
            p += 2; // GBK编码是双字节
        } else {
            // 不是有效的GBK编码，跳过
            ESP_LOGW(TAG, "无效的GBK编码字节: 0x%02X", *p);
            p++;
        }
    }
    
    return utf8_result;
}

// 增强的自定义映射函数，先尝试使用硬编码映射，再尝试通用转换
static std::string map_filename_by_hex(const char* filename) {
    // 创建一个十六进制字符串用于比较
    std::string hex_str = bytes_to_hex((const uint8_t*)filename, strlen(filename));
    // 移除十六进制字符串中的空格
    std::string clean_hex;
    for (char c : hex_str) {
        if (c != ' ') {
            clean_hex += c;
        }
    }
    
    // 特定文件的硬编码映射
    if (clean_hex.find("B6AACAD6BEEE2E4D5033") != std::string::npos) {
        return "丢手绢.MP3";
    } else if (clean_hex.find("D0A1CFBC2E4D5033") != std::string::npos) {
        return "小霞.MP3";
    } else if (clean_hex.find("D7F9CEBB2E4D5033") != std::string::npos) {
        return "座位.MP3";
    } else if (clean_hex.find("B8E6B0D7C6F8C7F22E4D5033") != std::string::npos) {
        return "告白气球.MP3";
    } else if (clean_hex.find("B0AEB4ED2E4D5033") != std::string::npos) {
        return "爱错.MP3";
    } 
    // 添加日志中显示的特定文件名映射
    else if (clean_hex.find("B1F0C8C3B0AE7E312E4D5033") != std::string::npos) {
        return "别让爱~1.MP3";
    } else if (clean_hex.find("D7DFD4DAC0E47E312E4D5033") != std::string::npos) {
        return "走在冷~1.MP3";
    } else if (clean_hex.find("B4BAB7E7D0ED7E312E4D5033") != std::string::npos) {
        return "春风许~1.MP3";
    }
    // 添加新发现的特定文件名映射
    else if (clean_hex.find("D0A6CBC0CED2C1CB2E4D5033") != std::string::npos) {
        return "笑死我了.MP3";
    } else if (clean_hex.find("C4E3CAC7CBAD2E4D5033") != std::string::npos) {
        return "你是谁.MP3";
    } else if (clean_hex.find("D4F5C3B4CBB52E4D5033") != std::string::npos) {
        return "怎么说.MP3";
    }
    // 添加最新发现的文件名映射
    else if (clean_hex.find("CDA6BAC3B5C4B0A12E4D5033") != std::string::npos) {
        return "哈哈好的啊.MP3";
    } else if (clean_hex.find("BECDD5E2D1F9B0C92E4D5033") != std::string::npos) {
        return "就这样吧.MP3";
    } else if (clean_hex.find("D7EEBDFCD4F57E312E4D5033") != std::string::npos) {
        return "最近怎~1.MP3";
    }
    
    // 记录未硬编码映射的文件的十六进制表示，便于后续添加
    ESP_LOGI(TAG, "未硬编码的文件十六进制表示: %s", clean_hex.c_str());
    
    // 如果找不到硬编码映射，尝试通用转换，但已知这部分有问题
    return gbk_to_utf8(filename);
}

// 添加辅助函数用于显示文件名的原始字节和显示形式
static void debug_filename(const char* filename) {
    size_t len = strlen(filename);
    ESP_LOGI(TAG, "文件名: [%s], 长度: %d", filename, len);
    ESP_LOGI(TAG, "十六进制: %s", bytes_to_hex((const uint8_t*)filename, len).c_str());
}

// 专门用于处理SD卡文件名的函数，包含更详细的调试信息
static std::string process_sd_filename(const char* original_filename) {
    if (!original_filename || strlen(original_filename) == 0) {
        return "";
    }
    
    // 打印原始文件名
    ESP_LOGI(TAG, "处理SD卡文件名: [%s]", original_filename);
    
    // 获取十六进制表示
    std::string hex_string = bytes_to_hex((const uint8_t*)original_filename, strlen(original_filename));
    ESP_LOGI(TAG, "文件名十六进制: %s", hex_string.c_str());
    
    // 检查文件名是否已经是UTF-8编码
    bool is_utf8 = true;
    const uint8_t* str = (const uint8_t*)original_filename;
    size_t len = strlen(original_filename);
    
    for (size_t i = 0; i < len; i++) {
        if (str[i] < 0x80) {
            // ASCII字符，继续
            continue;
        } else if ((str[i] & 0xE0) == 0xC0) {
            // 2字节UTF-8序列
            if (i + 1 >= len || (str[i+1] & 0xC0) != 0x80) {
                is_utf8 = false;
                break;
            }
            i += 1;
        } else if ((str[i] & 0xF0) == 0xE0) {
            // 3字节UTF-8序列
            if (i + 2 >= len || (str[i+1] & 0xC0) != 0x80 || (str[i+2] & 0xC0) != 0x80) {
                is_utf8 = false;
                break;
            }
            i += 2;
        } else if ((str[i] & 0xF8) == 0xF0) {
            // 4字节UTF-8序列
            if (i + 3 >= len || (str[i+1] & 0xC0) != 0x80 || (str[i+2] & 0xC0) != 0x80 || (str[i+3] & 0xC0) != 0x80) {
                is_utf8 = false;
                break;
            }
            i += 3;
        } else {
            // 不是有效的UTF-8序列
            is_utf8 = false;
            break;
        }
    }
    
    if (is_utf8) {
        ESP_LOGI(TAG, "文件名已经是UTF-8编码，无需转换: [%s]", original_filename);
        return original_filename;
    }
    
    // 如果不是UTF-8，则尝试从GBK转换
    ESP_LOGI(TAG, "文件名不是UTF-8编码，尝试从GBK转换");
    
    // 直接使用组件提供的GBK转换函数
    char* output_buffer = (char*)malloc(strlen(original_filename) * 4 + 1); 
    if (!output_buffer) {
        ESP_LOGE(TAG, "内存分配失败");
        return original_filename;
    }
    
    char* temp_ptr = output_buffer;
    int out_len = gbk_to_utf8((void**)&temp_ptr, (void*)original_filename, strlen(original_filename));
    
    if (out_len > 0) {
        std::string result = std::string(output_buffer);
        free(output_buffer);
        
        if (strcmp(result.c_str(), original_filename) != 0) {
            ESP_LOGI(TAG, "文件名转换结果(GBK库): [%s] -> [%s]", original_filename, result.c_str());
            return result;
        }
    } else {
        free(output_buffer);
    }
    
    // 如果组件转换失败，尝试硬编码映射（作为备选）
    std::string mapped_name = map_filename_by_hex(original_filename);
    
    // 如果转换后的结果不同于原始文件名，显示转换结果
    if (strcmp(mapped_name.c_str(), original_filename) != 0) {
        ESP_LOGI(TAG, "文件名转换结果(硬编码): [%s] -> [%s]", original_filename, mapped_name.c_str());
    } else {
        ESP_LOGI(TAG, "文件名未发生变化: [%s]", original_filename);
    }
    
    return mapped_name;
}

class JiuchuangDevBoard : public WifiBoard
{
private:
    // 声明为友元函数，允许访问私有成员
    friend void sd_card_detect_task(void *arg);
    friend void audio_event_callback(audio_player_cb_ctx_t *ctx);

    i2c_master_bus_handle_t codec_i2c_bus_;
    Button boot_button_;
    Button pwr_button_;
    Button wifi_button;
    Button cmd_button;
    LcdDisplay *display_;
    PowerSaveTimer *power_save_timer_;
    PowerManager *power_manager_;
    esp_lcd_panel_io_handle_t panel_io = NULL;
    esp_lcd_panel_handle_t panel = NULL;
    sdmmc_card_t *card = NULL;
    sdmmc_host_t host;
    sdmmc_slot_config_t slot_config;
    std::vector<std::string> audio_files;
    bool card_mounted = false;
    bool audio_player_initialized = false;
    int current_volume = 80; // 添加当前音量存储变量，初始值设为80
    bool is_playing = false; // 当前是否处于音乐播放状态
    TaskHandle_t sd_card_detect_task_handle = NULL;

    // 音量映射函数：将内部音量(0-80)映射为显示音量(0-100%)
    int MapVolumeForDisplay(int internal_volume) {
        // 确保输入在有效范围内
        if (internal_volume < 0) internal_volume = 0;
        if (internal_volume > 80) internal_volume = 80;
        
        // 将0-80映射到0-100
        // 公式: 显示音量 = (内部音量 / 80) * 100
        return (internal_volume * 100) / 80;
    }

public:
    bool is_switching = false; // 防止快速连续切换音乐 - 移至公有部分供回调访问
    
    // 保存音量到NVS
    void SaveVolumeToNVS(int volume) {
        nvs_handle_t nvs_handle;
        esp_err_t err = nvs_open("storage", NVS_READWRITE, &nvs_handle);
        if (err != ESP_OK) {
            ESP_LOGE(TAG, "Error opening NVS handle: %s", esp_err_to_name(err));
            return;
        }
        
        err = nvs_set_i32(nvs_handle, "volume", volume);
        if (err != ESP_OK) {
            ESP_LOGE(TAG, "Error writing volume to NVS: %s", esp_err_to_name(err));
        }
        
        err = nvs_commit(nvs_handle);
        if (err != ESP_OK) {
            ESP_LOGE(TAG, "Error committing NVS: %s", esp_err_to_name(err));
        }
        
        nvs_close(nvs_handle);
    }
    
    // 从NVS获取音量
    int LoadVolumeFromNVS() {
        nvs_handle_t nvs_handle;
        esp_err_t err = nvs_open("storage", NVS_READONLY, &nvs_handle);
        if (err != ESP_OK) {
            ESP_LOGI(TAG, "NVS不存在，使用默认音量");
            return 60; // 默认音量改为60（原来是80的75%）
        }
        
        int32_t volume = 60; // 默认音量改为60
        err = nvs_get_i32(nvs_handle, "volume", &volume);
        if (err != ESP_OK && err != ESP_ERR_NVS_NOT_FOUND) {
            ESP_LOGE(TAG, "Error reading volume from NVS: %s", esp_err_to_name(err));
        }
        
        nvs_close(nvs_handle);
        
        // 确保音量在有效范围内
        if (volume < 0) volume = 0;
        if (volume > 80) volume = 80; // 最大音量限制为80
        
        return volume;
    }

    // 公共初始化方法
public:
    static JiuchuangDevBoard *audio_board_instance;
    std::string current_file; // 当前播放的文件路径 - 移至公有部分以便audio_event_callback访问
    
    // 获取所有音频文件列表
    std::vector<std::string> GetAudioFiles(const char *mount_point)
    {
        std::vector<std::string> files;
        DIR *dir = opendir(mount_point);
        if (!dir)
        {
            ESP_LOGE(TAG, "无法打开目录: %s", mount_point);
            return files;
        }

        ESP_LOGI(TAG, "扫描目录 %s 中的音频文件", mount_point);
        struct dirent *entry;
        while ((entry = readdir(dir)) != NULL)
        {
            // 使用d_name可能会有编码问题，尝试打印原始字节值
            const char *filename = entry->d_name;
            if (filename[0] == 0) continue; // 跳过空文件名
            
            // 使用辅助函数显示文件名
            debug_filename(filename);
            
            // 尝试使用映射函数转换文件名
            std::string mapped_name = process_sd_filename(filename);
            if (mapped_name != filename) {
                ESP_LOGI(TAG, "文件名映射: [%s] -> [%s]", filename, mapped_name.c_str());
            }
            
            if (is_supported_audio_file(filename))
            {
                char filepath[512];
                snprintf(filepath, sizeof(filepath), "%s/%s", mount_point, filename);
                files.push_back(filepath);
                ESP_LOGI(TAG, "添加音频文件: %s", filepath);
            }
        }
        closedir(dir);

        // 按名称排序
        std::sort(files.begin(), files.end());
        
        // 打印找到的所有文件
        ESP_LOGI(TAG, "找到 %d 个音频文件:", files.size());
        for (size_t i = 0; i < files.size(); i++) {
            size_t pos = files[i].find_last_of("/\\");
            std::string filename = (pos != std::string::npos) ? files[i].substr(pos + 1) : files[i];
            std::string mapped_name = process_sd_filename(filename.c_str());
            ESP_LOGI(TAG, "[%d] %s -> %s", i, files[i].c_str(), mapped_name.c_str());
        }
        
        return files;
    }
    
    // 播放指定文件
    bool PlayFile(const std::string &filepath)
    {
        // 首先检查是否处于播放模式
        if (!IsPlaying()) {
            ESP_LOGI(TAG, "当前不处于音乐播放模式，不开始播放");
            return false;
        }
        
        ESP_LOGI(TAG, "尝试播放: %s", filepath.c_str());
        FILE *file = fopen(filepath.c_str(), "rb");
        if (file)
        {
            // 确保应用状态正确
            auto &app = Application::GetInstance();
            auto current_state = app.GetDeviceState();
            
            // 检查当前状态，如果不是音乐播放状态，更新状态
            if (current_state != DeviceState::kDeviceStateMusicPlaying) {
                ESP_LOGI(TAG, "设置应用状态为音乐播放");
                app.SetDeviceState(DeviceState::kDeviceStateMusicPlaying);
                
                // 确保已禁用语音功能
                app.DisableVoiceFeatures();
            }
            
            // 记录当前文件
            current_file = filepath;
            
            // 更新用户界面
            auto display = GetDisplay();
            if (display) {
                // 提取文件名（不含路径）
                size_t pos = filepath.find_last_of("/\\");
                std::string filename = (pos != std::string::npos) ? filepath.substr(pos + 1) : filepath;
                
                // 打印文件名的十六进制值，用于调试
                std::string hex_str = "";
                for (int i = 0; i < filename.length(); i++) {
                    char buf[8];
                    snprintf(buf, sizeof(buf), "%02X ", (unsigned char)filename[i]);
                    hex_str += buf;
                }
                ESP_LOGI(TAG, "显示文件名: [%s], 十六进制: %s", filename.c_str(), hex_str.c_str());
                
                // 使用映射函数转换文件名
                std::string displayName = process_sd_filename(filename.c_str());
                ESP_LOGI(TAG, "转换后的文件名: [%s]", displayName.c_str());
                
                std::string status_text = "正在播放: " + displayName;
                display->SetStatus(status_text.c_str());
                display->SetEmotion("happy");
                
                // 在聊天消息中也显示当前播放的文件名
                display->SetChatMessage("system", status_text.c_str());
            }
            
            // 开始播放
            ESP_LOGI(TAG, "开始播放: %s", filepath.c_str());
            audio_player_play(file);
            
            return true;
        }
        ESP_LOGE(TAG, "无法打开文件: %s", filepath.c_str());
        return false;
    }
    
    // 播放下一首歌
    bool PlayNextSong()
    {
        const char mount_point[] = "/sdcard";

        ESP_LOGI(TAG, "=== 开始播放下一首歌曲 ===");
        ESP_LOGI(TAG, "当前文件: %s", current_file.c_str());

        // 检查SD卡状态
        if (!card_mounted) {
            ESP_LOGE(TAG, "SD卡未挂载，无法播放下一首");
            return false;
        }

        // 获取音频文件列表
        audio_files = GetAudioFiles(mount_point);
        if (audio_files.empty())
        {
            ESP_LOGE(TAG, "未找到音频文件");
            return false;
        }

        ESP_LOGI(TAG, "找到 %d 个音频文件", audio_files.size());

        // 找到当前文件的下一个文件
        auto it = std::find(audio_files.begin(), audio_files.end(), current_file);

        std::string next_file;
        int current_index = -1;
        int next_index = 0;

        if (it == audio_files.end())
        {
            // 当前文件未找到，播放第一个
            next_file = audio_files.front();
            next_index = 0;
            ESP_LOGW(TAG, "当前文件未找到，播放第一个文件 (索引: %d)", next_index);
        }
        else
        {
            // 找到当前文件的索引
            current_index = std::distance(audio_files.begin(), it);
            ESP_LOGI(TAG, "当前文件索引: %d", current_index);
            
            // 计算下一个文件的索引
            next_index = (current_index + 1) % audio_files.size();
            next_file = audio_files[next_index];
            
            if (next_index == 0) {
                ESP_LOGI(TAG, "已到最后一首，循环到第一首 (索引: %d)", next_index);
            } else {
                ESP_LOGI(TAG, "播放下一首 (索引: %d)", next_index);
            }
        }

        ESP_LOGI(TAG, "下一首文件: %s", next_file.c_str());

        // 检查文件是否存在
        FILE* test_file = fopen(next_file.c_str(), "rb");
        if (!test_file) {
            ESP_LOGE(TAG, "下一首文件不存在: %s", next_file.c_str());
            return false;
        }
        fclose(test_file);

        // 播放文件
        ESP_LOGI(TAG, "开始播放下一首文件");
        bool success = PlayFile(next_file);
        if (!success) {
            ESP_LOGE(TAG, "播放下一首失败: %s", next_file.c_str());
        } else {
            ESP_LOGI(TAG, "成功开始播放下一首: %s", next_file.c_str());
        }
        
        ESP_LOGI(TAG, "=== 播放下一首歌曲完成 ===");
        return success;
    }
    
    // 播放上一首歌
    bool PlayPreviousSong()
    {
        const char mount_point[] = "/sdcard";

        ESP_LOGI(TAG, "=== 开始播放上一首歌曲 ===");
        ESP_LOGI(TAG, "当前文件: %s", current_file.c_str());

        // 检查SD卡状态
        if (!card_mounted) {
            ESP_LOGE(TAG, "SD卡未挂载，无法播放上一首");
            return false;
        }

        // 获取音频文件列表
        audio_files = GetAudioFiles(mount_point);
        if (audio_files.empty())
        {
            ESP_LOGE(TAG, "未找到音频文件");
            return false;
        }

        ESP_LOGI(TAG, "找到 %d 个音频文件", audio_files.size());

        // 找到当前文件的前一个文件
        auto it = std::find(audio_files.begin(), audio_files.end(), current_file);

        std::string prev_file;
        int current_index = -1;
        int prev_index = 0;

        if (it == audio_files.end())
        {
            // 当前文件未找到，播放最后一个
            prev_index = audio_files.size() - 1;
            prev_file = audio_files.back();
            ESP_LOGW(TAG, "当前文件未找到，播放最后一个文件 (索引: %d)", prev_index);
        }
        else
        {
            // 找到当前文件的索引
            current_index = std::distance(audio_files.begin(), it);
            ESP_LOGI(TAG, "当前文件索引: %d", current_index);
            
            // 计算上一个文件的索引
            prev_index = (current_index - 1 + audio_files.size()) % audio_files.size();
            prev_file = audio_files[prev_index];
            
            if (current_index == 0) {
                ESP_LOGI(TAG, "已到第一首，循环到最后一首 (索引: %d)", prev_index);
            } else {
                ESP_LOGI(TAG, "播放上一首 (索引: %d)", prev_index);
            }
        }

        ESP_LOGI(TAG, "上一首文件: %s", prev_file.c_str());

        // 检查文件是否存在
        FILE* test_file = fopen(prev_file.c_str(), "rb");
        if (!test_file) {
            ESP_LOGE(TAG, "上一首文件不存在: %s", prev_file.c_str());
            return false;
        }
        fclose(test_file);

        // 播放文件
        ESP_LOGI(TAG, "开始播放上一首文件");
        bool success = PlayFile(prev_file);
        if (!success) {
            ESP_LOGE(TAG, "播放上一首失败: %s", prev_file.c_str());
        } else {
            ESP_LOGI(TAG, "成功开始播放上一首: %s", prev_file.c_str());
        }
        
        ESP_LOGI(TAG, "=== 播放上一首歌曲完成 ===");
        return success;
    }

    // 安全的切换到上一首
    bool SwitchToPreviousSong() {
        ESP_LOGI(TAG, "*** 开始切换到上一首 ***");
        ESP_LOGI(TAG, "当前播放状态: %s", is_playing ? "播放中" : "未播放");
        ESP_LOGI(TAG, "当前切换状态: %s", is_switching ? "切换中" : "空闲");
        
        if (!is_playing) {
            ESP_LOGW(TAG, "当前未在播放音乐，无法切换");
            return false;
        }
        
        // 防抖：检查是否正在切换
        if (is_switching) {
            ESP_LOGI(TAG, "正在切换中，忽略操作");
            return false;
        }
        
        is_switching = true;
        ESP_LOGI(TAG, "设置切换状态为true");
        
        // 显示切换状态
        auto display = GetDisplay();
        if (display) {
            display->ShowNotification("切换到上一首...");
            ESP_LOGI(TAG, "显示切换通知");
        }
        
        // 停止当前播放
        ESP_LOGI(TAG, "停止当前播放，准备切换到上一首");
        audio_player_state_t current_state = audio_player_get_state();
        ESP_LOGI(TAG, "当前播放器状态: %d", current_state);
        
        audio_player_stop();
        ESP_LOGI(TAG, "已调用audio_player_stop()");
        
        // 等待播放器真正停止
        int timeout = 50; // 5秒超时
        ESP_LOGI(TAG, "等待播放器停止，超时时间: %d * 100ms", timeout);
        
        while (audio_player_get_state() != AUDIO_PLAYER_STATE_IDLE && timeout > 0) {
            current_state = audio_player_get_state();
            ESP_LOGD(TAG, "等待停止中，当前状态: %d, 剩余超时: %d", current_state, timeout);
            vTaskDelay(pdMS_TO_TICKS(100));
            timeout--;
        }
        
        current_state = audio_player_get_state();
        ESP_LOGI(TAG, "等待结束，最终状态: %d, 剩余超时: %d", current_state, timeout);
        
        if (timeout <= 0) {
            ESP_LOGE(TAG, "停止播放超时，当前状态: %d", current_state);
            is_switching = false;
            if (display) {
                display->ShowNotification("切换超时");
            }
            return false;
        }
        
        ESP_LOGI(TAG, "播放器已停止，开始播放上一首");
        
        // 播放上一首
        bool success = PlayPreviousSong();
        
        // 如果播放成功，等待一小段时间确保播放稳定启动
        if (success) {
            ESP_LOGI(TAG, "等待播放稳定启动...");
            vTaskDelay(pdMS_TO_TICKS(200)); // 等待200ms
        }
        
        is_switching = false;
        ESP_LOGI(TAG, "重置切换状态为false");
        
        if (!success) {
            ESP_LOGE(TAG, "播放上一首失败");
            if (display) {
                display->ShowNotification("切换失败");
            }
        } else {
            ESP_LOGI(TAG, "成功切换到上一首");
            if (display) {
                display->ShowNotification("已切换到上一首");
            }
        }
        
        ESP_LOGI(TAG, "*** 切换到上一首完成，结果: %s ***", success ? "成功" : "失败");
        return success;
    }

    // 安全的切换到下一首
    bool SwitchToNextSong() {
        ESP_LOGI(TAG, "*** 开始切换到下一首 ***");
        ESP_LOGI(TAG, "当前播放状态: %s", is_playing ? "播放中" : "未播放");
        ESP_LOGI(TAG, "当前切换状态: %s", is_switching ? "切换中" : "空闲");
        
        if (!is_playing) {
            ESP_LOGW(TAG, "当前未在播放音乐，无法切换");
            return false;
        }
        
        // 防抖：检查是否正在切换
        if (is_switching) {
            ESP_LOGI(TAG, "正在切换中，忽略操作");
            return false;
        }
        
        is_switching = true;
        ESP_LOGI(TAG, "设置切换状态为true");
        
        // 显示切换状态
        auto display = GetDisplay();
        if (display) {
            display->ShowNotification("切换到下一首...");
            ESP_LOGI(TAG, "显示切换通知");
        }
        
        // 停止当前播放
        ESP_LOGI(TAG, "停止当前播放，准备切换到下一首");
        audio_player_state_t current_state = audio_player_get_state();
        ESP_LOGI(TAG, "当前播放器状态: %d", current_state);
        
        audio_player_stop();
        ESP_LOGI(TAG, "已调用audio_player_stop()");
        
        // 等待播放器真正停止
        int timeout = 50; // 5秒超时
        ESP_LOGI(TAG, "等待播放器停止，超时时间: %d * 100ms", timeout);
        
        while (audio_player_get_state() != AUDIO_PLAYER_STATE_IDLE && timeout > 0) {
            current_state = audio_player_get_state();
            ESP_LOGD(TAG, "等待停止中，当前状态: %d, 剩余超时: %d", current_state, timeout);
            vTaskDelay(pdMS_TO_TICKS(100));
            timeout--;
        }
        
        current_state = audio_player_get_state();
        ESP_LOGI(TAG, "等待结束，最终状态: %d, 剩余超时: %d", current_state, timeout);
        
        if (timeout <= 0) {
            ESP_LOGE(TAG, "停止播放超时，当前状态: %d", current_state);
            is_switching = false;
            if (display) {
                display->ShowNotification("切换超时");
            }
            return false;
        }
        
        ESP_LOGI(TAG, "播放器已停止，开始播放下一首");
        
        // 播放下一首
        bool success = PlayNextSong();
        
        // 如果播放成功，等待一小段时间确保播放稳定启动
        if (success) {
            ESP_LOGI(TAG, "等待播放稳定启动...");
            vTaskDelay(pdMS_TO_TICKS(200)); // 等待200ms
        }
        
        is_switching = false;
        ESP_LOGI(TAG, "重置切换状态为false");
        
        if (!success) {
            ESP_LOGE(TAG, "播放下一首失败");
            if (display) {
                display->ShowNotification("切换失败");
            }
        } else {
            ESP_LOGI(TAG, "成功切换到下一首");
            if (display) {
                display->ShowNotification("已切换到下一首");
            }
        }
        
        ESP_LOGI(TAG, "*** 切换到下一首完成，结果: %s ***", success ? "成功" : "失败");
        return success;
    }

    void InitializePowerManager()
    {
        power_manager_ = new PowerManager(PWR_ADC_GPIO);
        power_manager_->OnChargingStatusChanged([this](bool is_charging)
                                                {
            if (is_charging) {
                power_save_timer_->SetEnabled(false);
            } else {
                power_save_timer_->SetEnabled(true);
            } });
    }

    void InitializeSdCard()
    {
        // 配置SD卡主机
        host = SDMMC_HOST_DEFAULT();

        // 配置SD卡插槽
        slot_config = SDMMC_SLOT_CONFIG_DEFAULT();
        slot_config.width = 1; // 1位模式
        slot_config.clk = SD_CARD_CLK_PIN;
        slot_config.cmd = SD_CARD_CMD_PIN;
        slot_config.d0 = SD_CARD_DAT0_PIN;
        slot_config.flags |= SDMMC_SLOT_FLAG_INTERNAL_PULLUP;
    }

    void InitializePowerSaveTimer()
    {
#ifndef __USER_GPIO_PWRDOWN__
        RTC_DATA_ATTR static bool long_press_occurred = false;
        esp_sleep_wakeup_cause_t cause = esp_sleep_get_wakeup_cause();
        if (cause == ESP_SLEEP_WAKEUP_EXT0)
        {
            ESP_LOGI(TAG, "Wake up by EXT0");
            const int64_t start = esp_timer_get_time();
            ESP_LOGI(TAG, "esp_sleep_get_wakeup_cause");
            while (gpio_get_level(PWR_BUTTON_GPIO) == 0)
            {
                if (esp_timer_get_time() - start > 3000000)
                {
                    long_press_occurred = true;
                    break;
                }
                vTaskDelay(100 / portTICK_PERIOD_MS);
            }

            if (long_press_occurred)
            {
                ESP_LOGI(TAG, "Long press wakeup");
                long_press_occurred = false;
            }
            else
            {
                ESP_LOGI(TAG, "Short press, return to sleep");
                ESP_ERROR_CHECK(esp_sleep_enable_ext0_wakeup(PWR_BUTTON_GPIO, 0));
                ESP_ERROR_CHECK(rtc_gpio_pullup_en(PWR_BUTTON_GPIO)); // 内部上拉
                ESP_ERROR_CHECK(rtc_gpio_pulldown_dis(PWR_BUTTON_GPIO));
                esp_deep_sleep_start();
            }
        }
#endif
        // 一分钟进入浅睡眠，5分钟进入深睡眠关机
        power_save_timer_ = new PowerSaveTimer(-1, (60 * 10), (60 * 30));
        // power_save_timer_ = new PowerSaveTimer(-1, 6, 10);//test
        power_save_timer_->OnEnterSleepMode([this]()
                                            {
            ESP_LOGI(TAG, "Enabling sleep mode");
            display_->SetChatMessage("system", "");
            display_->SetEmotion("sleepy");
            GetBacklight()->SetBrightness(1); });
        power_save_timer_->OnExitSleepMode([this]()
                                           {
            display_->SetChatMessage("system", "");
            display_->SetEmotion("neutral");
            GetBacklight()->RestoreBrightness(); });
        power_save_timer_->OnShutdownRequest([this]()
                                             {
                                                 ESP_LOGI(TAG, "Shutting down");
#ifndef __USER_GPIO_PWRDOWN__
                                                 ESP_ERROR_CHECK(esp_sleep_enable_ext0_wakeup(PWR_BUTTON_GPIO, 0));
                                                 ESP_ERROR_CHECK(rtc_gpio_pullup_en(PWR_BUTTON_GPIO)); // 内部上拉
                                                 ESP_ERROR_CHECK(rtc_gpio_pulldown_dis(PWR_BUTTON_GPIO));

                                                 esp_lcd_panel_disp_on_off(panel, false); // 关闭显示
                                                 esp_deep_sleep_start();
#else
                                                 rtc_gpio_set_level(PWR_EN_GPIO, 0);
                                                 rtc_gpio_hold_dis(PWR_EN_GPIO);
#endif
                                             });
        power_save_timer_->SetEnabled(true);
    }

    void InitializeI2c()
    {
        // Initialize I2C peripheral
        i2c_master_bus_config_t i2c_bus_cfg = {
            .i2c_port = (i2c_port_t)1,
            .sda_io_num = AUDIO_CODEC_I2C_SDA_PIN,
            .scl_io_num = AUDIO_CODEC_I2C_SCL_PIN,
            .clk_source = I2C_CLK_SRC_DEFAULT,
            .glitch_ignore_cnt = 7,
            .intr_priority = 0,
            .trans_queue_depth = 0,
            .flags = {
                .enable_internal_pullup = 1,
            },
        };
        ESP_ERROR_CHECK(i2c_new_master_bus(&i2c_bus_cfg, &codec_i2c_bus_));
    }

    void InitializeSpi()
    {
    }

    void InitializeButtons()
    {
        static bool pwrbutton_unreleased = false;
        static int power_button_click_count = 0;
        static int64_t last_power_button_press_time = 0;
        
        if (gpio_get_level(GPIO_NUM_3) == 1)
        {
            pwrbutton_unreleased = true;
        }

        // 电源按钮按下和松开事件处理
        pwr_button_.OnPressUp([this]()
                              {
            ESP_LOGI(TAG, "电源按钮按下: %s %d", __FUNCTION__, __LINE__);
            pwrbutton_unreleased = false;
            int64_t current_time = esp_timer_get_time();
            if (current_time - last_power_button_press_time < 1000000) { // 1秒内
                power_button_click_count++;
                
                // 三击重置WiFi
                if (power_button_click_count >= 3) {
                    ESP_LOGI(TAG, "三击重置WiFi");
                    rtc_gpio_set_level(PWR_EN_GPIO, 1);
                    rtc_gpio_hold_en(PWR_EN_GPIO);
                    ResetWifiConfiguration();
                    power_button_click_count = 0;
                    return;
                }
            } else {
                power_button_click_count = 1;
            }
            
            last_power_button_press_time = current_time;
            // 获取当前应用实例和状态
            auto &app = Application::GetInstance();
            auto current_state = app.GetDeviceState();

            // 如果正在播放音乐，退出音乐播放模式
            if (IsPlaying() || current_state == kDeviceStateMusicPlaying)
            {
                ESP_LOGI(TAG, "检测到音乐播放状态，正在退出...");
                
                // 先停止所有音频播放
                ESP_LOGI(TAG, "停止音频播放");
                audio_player_stop();
                
                // 等待一小段时间确保停止处理完成
                vTaskDelay(pdMS_TO_TICKS(100));
                
                // 强制重置播放状态标志
                ESP_LOGI(TAG, "强制重置播放状态标志");
                SetPlaying(false);
                
                // 获取显示对象和音频编解码器
                auto display = GetDisplay();
                auto codec = GetAudioCodec();
                
                // 重新配置音频编解码器
                ESP_LOGI(TAG, "重新配置音频编解码器");
                codec->SetSampleRate(24000, 1);
                codec->EnableOutput(false);
                codec->EnableInput(true);
                
                // 重新启用语音功能
                ESP_LOGI(TAG, "重新启用语音功能");
                app.EnableVoiceFeatures();
                
                // 强制设置为待机状态
                ESP_LOGI(TAG, "强制设置为待机状态");
                app.SetDeviceState(DeviceState::kDeviceStateIdle);
                
                // 更新显示
                ESP_LOGI(TAG, "更新显示状态");
                display->SetStatus(Lang::Strings::STANDBY);
                display->SetEmotion("neutral");
                
                ESP_LOGI(TAG, "成功退出音乐播放模式，切换到小智模式");
                
                // 唤醒设备，防止立即进入睡眠
                power_save_timer_->WakeUp();
            }
            else
            {
                ESP_LOGI(TAG, "当前设备状态: %d", current_state);
                
                if (current_state == kDeviceStateIdle) {
                    // 如果当前是待命状态，切换到聆听状态
                    ESP_LOGI(TAG, "从待命状态切换到聆听状态");
                    app.ToggleChatState(); // 切换到聆听状态
                } else if (current_state == kDeviceStateListening) {
                    // 如果当前是聆听状态，切换到待命状态
                    ESP_LOGI(TAG, "从聆听状态切换到待命状态");
                    app.ToggleChatState(); // 切换到待命状态
                } else if (current_state == kDeviceStateSpeaking) {
                    // 如果当前是说话状态，终止说话并切换到待命状态
                    ESP_LOGI(TAG, "从说话状态切换到待命状态");
                    app.ToggleChatState(); // 终止说话
                } else {
                    // 其他状态下只唤醒设备
                    ESP_LOGI(TAG, "唤醒设备");
                power_save_timer_->WakeUp();
                }
            }
        });

        // 电源按钮长按事件
        pwr_button_.OnLongPress([this]()
                                {
            ESP_LOGI(TAG, "电源按钮长按");
                                    if (pwrbutton_unreleased)
                                        return;

            // 如果在音乐播放模式，先停止播放
            if (IsPlaying()) {
                ESP_LOGI(TAG, "从音乐播放模式退出并关机");
                audio_player_stop();
                SetPlaying(false);
            }
            
            // 长按前保存当前音量
            ESP_LOGI(TAG, "保存音量设置: %d", current_volume);
            SaveVolumeToNVS(current_volume);

                                    // 长按进入深度睡眠模式(关机)
#ifndef __USER_GPIO_PWRDOWN__
            ESP_LOGI(TAG, "准备进入深度睡眠模式");
                                    ESP_ERROR_CHECK(esp_sleep_enable_ext0_wakeup(PWR_BUTTON_GPIO, 0));
                                    ESP_ERROR_CHECK(rtc_gpio_pullup_en(PWR_BUTTON_GPIO)); // 内部上拉
                                    ESP_ERROR_CHECK(rtc_gpio_pulldown_dis(PWR_BUTTON_GPIO));
                                    ESP_LOGI(TAG, "Enter deep sleep");
                                    esp_deep_sleep_start();
#else
            ESP_LOGI(TAG, "准备进入深度睡眠模式");
                                    ESP_ERROR_CHECK(esp_sleep_enable_ext0_wakeup(PWR_BUTTON_GPIO, 0));
                                    ESP_ERROR_CHECK(rtc_gpio_pulldown_en(PWR_BUTTON_GPIO)); // 内部上拉
                                    ESP_ERROR_CHECK(rtc_gpio_pullup_dis(PWR_BUTTON_GPIO));
                                    ESP_LOGI(TAG, "Enter deep sleep");
                                    rtc_gpio_set_level(PWR_EN_GPIO, 0);
                                    rtc_gpio_hold_dis(PWR_EN_GPIO);
                                    esp_deep_sleep_start();
#endif
                                });

        // WIFI按钮功能
        wifi_button.OnClick([this]()
                            {
            if (is_playing) {
                // 在音乐模式下：播放上一首
                ESP_LOGI(TAG, "播放上一首");
                
                // 使用安全的切换方法
                SwitchToPreviousSong();
            } else {
                // 在小智状态下：加音量
                ESP_LOGI(TAG, "WIFI按钮：增加音量");
                // 调整音量，每次增加8个内部音量单位（对应显示10%）
                current_volume = (current_volume + 8 > 80) ? 80 : current_volume + 8;
                auto codec = GetAudioCodec();
                // 将0-80的音量映射到完整音量范围
                int actual_volume = current_volume;
                codec->SetOutputVolume(actual_volume);
                ESP_LOGI(TAG, "当前音量: %d, 实际音量: %d", current_volume, actual_volume);
                // 保存新的音量设置
                SaveVolumeToNVS(current_volume);
                power_save_timer_->WakeUp();
                
                // 在屏幕上显示当前音量（使用映射后的显示音量）
                auto display = GetDisplay();
                if (display) {
                    int display_volume = MapVolumeForDisplay(current_volume);
                    char volume_text[20];
                    snprintf(volume_text, sizeof(volume_text), "音量: %d%%", display_volume);
                    display->ShowNotification(volume_text);
                    ESP_LOGI(TAG, "显示音量: %d%% (内部音量: %d)", display_volume, current_volume);
                }
            }
        });

        // CMD按钮功能
        cmd_button.OnClick([this]()
                           {
            if (is_playing) {
                // 在音乐模式下：播放下一首
                ESP_LOGI(TAG, "播放下一首");
                
                // 使用安全的切换方法
                SwitchToNextSong();
            } else {
                // 在小智状态下：减音量
                ESP_LOGI(TAG, "CMD按钮：减少音量");
                // 调整音量，每次减少8个内部音量单位（对应显示10%）
                current_volume = (current_volume - 8 < 0) ? 0 : current_volume - 8;
                auto codec = GetAudioCodec();
                // 将0-80的音量映射到完整音量范围
                int actual_volume = current_volume;
                codec->SetOutputVolume(actual_volume);
                ESP_LOGI(TAG, "当前音量: %d, 实际音量: %d", current_volume, actual_volume);
                // 保存新的音量设置
                SaveVolumeToNVS(current_volume);
                power_save_timer_->WakeUp();
                
                // 在屏幕上显示当前音量（使用映射后的显示音量）
                auto display = GetDisplay();
                if (display) {
                    int display_volume = MapVolumeForDisplay(current_volume);
                    char volume_text[20];
                    snprintf(volume_text, sizeof(volume_text), "音量: %d%%", display_volume);
                    display->ShowNotification(volume_text);
                    ESP_LOGI(TAG, "显示音量: %d%% (内部音量: %d)", display_volume, current_volume);
                }
            }
        });

        // BOOT按钮功能不变，仅保留唤醒设备的功能
        boot_button_.OnClick([this]()
                             {
            // 仅唤醒设备
            power_save_timer_->WakeUp();
        });
    }

    void InitializeGC9301isplay()
    {
        // 液晶屏控制IO初始化
        ESP_LOGI(TAG, "test Install panel IO");
        spi_bus_config_t buscfg = {};
        buscfg.mosi_io_num = DISPLAY_SPI_MOSI_PIN;
        buscfg.sclk_io_num = DISPLAY_SPI_SCK_PIN;
        buscfg.miso_io_num = GPIO_NUM_NC;
        buscfg.quadwp_io_num = GPIO_NUM_NC;
        buscfg.quadhd_io_num = GPIO_NUM_NC;
        buscfg.max_transfer_sz = DISPLAY_WIDTH * DISPLAY_HEIGHT * sizeof(uint16_t);
        ESP_ERROR_CHECK(spi_bus_initialize(SPI3_HOST, &buscfg, SPI_DMA_CH_AUTO));

        // 初始化SPI总线
        esp_lcd_panel_io_spi_config_t io_config = {};
        io_config.cs_gpio_num = DISPLAY_SPI_CS_PIN;
        io_config.dc_gpio_num = DISPLAY_DC_PIN;
        io_config.spi_mode = 3;
        io_config.pclk_hz = 80 * 1000 * 1000;
        io_config.trans_queue_depth = 10;
        io_config.lcd_cmd_bits = 8;
        io_config.lcd_param_bits = 8;
        esp_lcd_new_panel_io_spi(SPI3_HOST, &io_config, &panel_io);

        // 初始化液晶屏驱动芯片9309
        ESP_LOGI(TAG, "Install LCD driver");
        esp_lcd_panel_dev_config_t panel_config = {};
        panel_config.reset_gpio_num = GPIO_NUM_NC;
        panel_config.rgb_ele_order = LCD_RGB_ENDIAN_BGR;
        panel_config.bits_per_pixel = 16;
        esp_lcd_new_panel_gc9309na(panel_io, &panel_config, &panel);

        esp_lcd_panel_reset(panel);

        esp_lcd_panel_init(panel);
        esp_lcd_panel_invert_color(panel, false);
        esp_lcd_panel_swap_xy(panel, DISPLAY_SWAP_XY);
        esp_lcd_panel_mirror(panel, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y);
        display_ = new SpiLcdDisplay(panel_io, panel,
                                     DISPLAY_WIDTH, DISPLAY_HEIGHT, DISPLAY_OFFSET_X, DISPLAY_OFFSET_Y, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y, DISPLAY_SWAP_XY,
                                     {
                                         .text_font = &font_puhui_20_4,
                                         .icon_font = &font_awesome_20_4,
#if CONFIG_USE_WECHAT_MESSAGE_STYLE
                                         .emoji_font = font_emoji_32_init(),
#else
                                         .emoji_font = font_emoji_64_init(),
#endif
                                     });
    }

    // 物联网初始化，添加对 AI 可见设备
    void InitializeIot()
    {
        auto &thing_manager = iot::ThingManager::GetInstance();
        thing_manager.AddThing(iot::CreateThing("Speaker"));
        thing_manager.AddThing(iot::CreateThing("Screen"));
        thing_manager.AddThing(iot::CreateThing("Battery"));
    }

    // 初始化mp3和wav播放器
    void InitializeAudioPlayer()
    {
        if (!audio_player_initialized)
        {
            // 存储实例指针供全局回调使用
            audio_board_instance = this;

            // 使用外部定义的回调函数
            audio_player_config_t config = {
                .mute_fn = audio_mute_callback,
                .clk_set_fn = audio_clk_set_callback,
                .write_fn = audio_write_callback,
                .priority = 7,
                .coreID = 1};

            esp_err_t ret = audio_player_new(config);
            if (ret == ESP_OK)
            {
                // 注册播放器状态变化回调
                audio_player_callback_register(audio_event_callback, NULL);

                audio_player_initialized = true;
                ESP_LOGI(TAG, "音频播放器初始化成功");
            }
            else
            {
                ESP_LOGE(TAG, "音频播放器初始化失败: %d", ret);
            }
        }
    }

    // 通过语音命令启动音乐播放
    virtual bool StartMusicPlayback(const std::string& music_name = "") override
    {
        ESP_LOGI(TAG, "准备启动音乐播放...");
        
        if (!card_mounted) {
            ESP_LOGE(TAG, "SD卡未挂载，无法播放音乐");
            return false;
        }

        // 初始化音频播放器（如果尚未初始化）
        if (!audio_player_initialized) {
            ESP_LOGI(TAG, "初始化音频播放器");
            InitializeAudioPlayer();
        }

        // 停止任何当前播放
        if (audio_player_get_state() != AUDIO_PLAYER_STATE_IDLE) {
            ESP_LOGI(TAG, "停止当前播放");
            audio_player_stop();
            vTaskDelay(pdMS_TO_TICKS(100)); // 等待停止完成
        }
        
        // 设置音乐播放状态
        ESP_LOGI(TAG, "设置音乐播放状态标志");
        SetPlaying(true);
        
        // 禁用语音功能
        ESP_LOGI(TAG, "禁用语音功能");
        auto &app = Application::GetInstance();
        app.DisableVoiceFeatures();
        
        // 设置应用状态
        ESP_LOGI(TAG, "设置应用状态为音乐播放");
        app.SetDeviceState(DeviceState::kDeviceStateMusicPlaying);
        
        // 配置音频编解码器
        ESP_LOGI(TAG, "配置音频编解码器");
        auto codec = GetAudioCodec();
        codec->EnableInput(false);
        codec->EnableOutput(true);
        
        // 更新显示状态
        ESP_LOGI(TAG, "更新显示状态");
        auto display = GetDisplay();
        display->SetStatus("音乐播放模式");
        display->SetEmotion("happy");

        // 列出所有SD卡中的音频文件
        ESP_LOGI(TAG, "扫描SD卡音频文件");
        const char mount_point[] = "/sdcard";
        audio_files = GetAudioFiles(mount_point);
        if (audio_files.empty()) {
            ESP_LOGI(TAG, "未找到音频文件");
            SetPlaying(false);
            restore_device_status();
            return false;
        }
        ESP_LOGI(TAG, "找到 %d 个音频文件", audio_files.size());

        // 如果提供了音乐名称，尝试查找匹配的文件
        if (!music_name.empty()) {
            ESP_LOGI(TAG, "尝试查找匹配音乐: %s", music_name.c_str());
            for (const auto& file : audio_files) {
                // 提取文件名部分（不含路径）
                size_t pos = file.find_last_of("/\\");
                std::string filename = (pos != std::string::npos) ? file.substr(pos + 1) : file;
                
                // 打印文件名的十六进制值和转换后的文件名
                std::string hex_str = bytes_to_hex((const uint8_t*)filename.c_str(), filename.length());
                std::string displayName = process_sd_filename(filename.c_str());
                ESP_LOGI(TAG, "检查文件: [%s], 转换后: [%s]", filename.c_str(), displayName.c_str());
                
                // 匹配逻辑：检查转换后的文件名是否包含要搜索的音乐名称
                if (displayName.find(music_name) != std::string::npos) {
                    ESP_LOGI(TAG, "找到匹配的音乐: %s -> %s", file.c_str(), displayName.c_str());
                    current_file = file; // 设置当前文件
                    FILE *fp = fopen(file.c_str(), "rb");
                    if (fp) {
                        ESP_LOGI(TAG, "开始播放匹配的音乐");
                        audio_player_play(fp);
                        return true;
                    }
                    ESP_LOGE(TAG, "无法打开文件: %s", file.c_str());
                    break;
                }
            }
            ESP_LOGI(TAG, "未找到匹配的音乐，将播放第一首");
        }

        // 如果没有找到匹配的文件或没有提供音乐名称，播放第一首
        ESP_LOGI(TAG, "播放第一首音乐");
        if (!audio_files.empty()) {
            current_file = audio_files[0]; // 设置为第一首歌
            FILE *fp = fopen(audio_files[0].c_str(), "rb");
            if (fp) {
                ESP_LOGI(TAG, "开始播放第一首音乐: %s", audio_files[0].c_str());
                audio_player_play(fp);
                return true;
            }
            ESP_LOGE(TAG, "无法打开文件: %s", audio_files[0].c_str());
        }
        
        // 如果到这里，说明播放失败
        ESP_LOGE(TAG, "播放失败，恢复设备状态");
        SetPlaying(false);
        restore_device_status();
        return false;
    }

    // 公共接口方法
public:
    JiuchuangDevBoard() : boot_button_(BOOT_BUTTON_GPIO),
                          pwr_button_(PWR_BUTTON_GPIO, true),
                          wifi_button(WIFI_BUTTON_GPIO),
                          cmd_button(CMD_BUTTON_GPIO)
    {
        // 初始化NVS
        esp_err_t err = nvs_flash_init();
        if (err == ESP_ERR_NVS_NO_FREE_PAGES || err == ESP_ERR_NVS_NEW_VERSION_FOUND) {
            // NVS分区已满或版本不匹配，擦除并重新初始化
            ESP_ERROR_CHECK(nvs_flash_erase());
            err = nvs_flash_init();
        }
        ESP_ERROR_CHECK(err);
        
        // 初始化GBK编码表
        ESP_LOGI(TAG, "初始化GBK编码表");
        init_gbk_encoding();
        
        // 从NVS加载保存的音量
        current_volume = LoadVolumeFromNVS();
        ESP_LOGI(TAG, "从NVS加载音量: %d", current_volume);

        InitializeI2c();
        InitializePowerManager();
        InitializePowerSaveTimer();
        InitializeSpi();
        InitializeButtons();
        InitializeGC9301isplay();
        InitializeIot();
        InitializeSdCard();
        InitializeAudioPlayer();
        
        // 设置加载的音量
        auto codec = GetAudioCodec();
        // 应用音量值
        int actual_volume = current_volume;
        codec->SetOutputVolume(actual_volume);
        ESP_LOGI(TAG, "设置初始音量: %d, 实际音量: %d", current_volume, actual_volume);
        
        GetBacklight()->RestoreBrightness();
    }

    // 获取音乐播放状态
    bool IsPlaying() const {
        return is_playing;
    }
    
    // 设置音乐播放状态
    void SetPlaying(bool playing) {
        is_playing = playing;
    }

    // virtual Led* GetLed() override {
    //     static SingleLed led(BUILTIN_LED_GPIO);
    //     return &led;
    // }

    virtual AudioCodec *GetAudioCodec() override
    {
        static Es8311AudioCodec audio_codec(
            codec_i2c_bus_,
            I2C_NUM_0,
            AUDIO_INPUT_SAMPLE_RATE,
            AUDIO_OUTPUT_SAMPLE_RATE,
            AUDIO_I2S_GPIO_MCLK,
            AUDIO_I2S_GPIO_BCLK,
            AUDIO_I2S_GPIO_WS,
            AUDIO_I2S_GPIO_DOUT,
            AUDIO_I2S_GPIO_DIN,
            AUDIO_CODEC_PA_PIN,
            AUDIO_CODEC_ES8311_ADDR);
        return &audio_codec;
    }

    virtual Display *GetDisplay() override
    {
        return display_;
    }

    virtual Backlight *GetBacklight() override
    {
        static PwmBacklight backlight(DISPLAY_BACKLIGHT_PIN, DISPLAY_BACKLIGHT_OUTPUT_INVERT);
        return &backlight;
    }

    virtual bool GetBatteryLevel(int &level, bool &charging, bool &discharging) override
    {
        static bool last_discharging = false;
        charging = power_manager_->IsCharging();
        discharging = power_manager_->IsDischarging();
        if (discharging != last_discharging)
        {
            power_save_timer_->SetEnabled(discharging);
            last_discharging = discharging;
        }
        level = power_manager_->GetBatteryLevel();
        return true;
    }

    virtual void SetPowerSaveMode(bool enabled) override
    {
        if (!enabled)
        {
            power_save_timer_->WakeUp();
        }
        WifiBoard::SetPowerSaveMode(enabled);
    }

    virtual void StartSdCardDetection()
    {
        if (sd_card_detect_task_handle == NULL)
        {
            xTaskCreate(
                sd_card_detect_task,
                "sd_card_detect",
                8192,
                this,
                6,
                &sd_card_detect_task_handle);
        }
    }
};

// 在类定义外部初始化静态成员变量
JiuchuangDevBoard *JiuchuangDevBoard::audio_board_instance = nullptr;

/**
 * @brief 列出SD卡中的文件
 *
 * @param mount_point 挂载点路径
 * @return esp_err_t ESP_OK表示成功
 */
static esp_err_t list_sd_card_files(const char *mount_point)
{
    char tmp_file_path[128];
    snprintf(tmp_file_path, sizeof(tmp_file_path), "%s/d.tmp", mount_point);
    FILE *tmp_file = fopen(tmp_file_path, "w");
    if (fclose(tmp_file) != 0)
    {
        ESP_LOGE(TAG, "SD卡已拔出");
        return ESP_FAIL;
    };
    unlink(tmp_file_path);

    // 继续列出SD卡中的文件
    ESP_LOGI(TAG, "SD卡文件列表:");
    DIR *dir = opendir(mount_point);
    if (!dir)
    {
        ESP_LOGE(TAG, "无法打开目录: %s", mount_point);
        return ESP_FAIL;
    }

    struct dirent *entry;
    int file_count = 0;
    int audio_file_count = 0;

    // 遍历并打印文件名
    while ((entry = readdir(dir)) != NULL)
    {
        // 使用辅助函数调试文件名
        const char* filename = entry->d_name;
        std::string mapped_name = process_sd_filename(filename);
        file_count++;
        
        // 检查是否是MP3文件
        if (is_supported_audio_file(filename)) {
            ESP_LOGI(TAG, "找到音频文件: %s -> %s", filename, mapped_name.c_str());
            audio_file_count++;
        }
    }

    closedir(dir);

    if (file_count == 0)
    {
        ESP_LOGI(TAG, "SD卡为空");
    }
    else
    {
        ESP_LOGI(TAG, "共有 %d 个文件，其中 %d 个音频文件", file_count, audio_file_count);
    }

    return ESP_OK;
}

// 静音/取消静音控制回调
static esp_err_t audio_mute_callback(AUDIO_PLAYER_MUTE_SETTING setting)
{
    ESP_LOGI(TAG, "mute setting %d", setting);
    return ESP_OK;
}

// 音频时钟设置回调
static esp_err_t audio_clk_set_callback(uint32_t rate, uint32_t bits_cfg, i2s_slot_mode_t ch)
{
    if (!JiuchuangDevBoard::audio_board_instance)
        return ESP_ERR_INVALID_STATE;
    auto &app = Application::GetInstance();
    app.DisableVoiceFeatures();
    app.SetDeviceState(DeviceState::kDeviceStateMusicPlaying);
    auto codec = JiuchuangDevBoard::audio_board_instance->GetAudioCodec();
    codec->EnableInput(false);
    codec->SetSampleRate(rate, (int)ch);
    ESP_LOGI(TAG, "音频时钟设置: rate=%lu, bits_cfg=%lu, ch=%d", rate, bits_cfg, (int)ch);
    return ESP_OK;
}

// 音频数据写入回调
static esp_err_t audio_write_callback(void *audio_buffer, size_t len, size_t *bytes_written, uint32_t timeout_ms)
{
    if (!JiuchuangDevBoard::audio_board_instance)
        return ESP_ERR_INVALID_STATE;

    auto codec = JiuchuangDevBoard::audio_board_instance->GetAudioCodec();
    int16_t *samples = (int16_t *)audio_buffer;
    int sample_count = len / sizeof(int16_t);

    // 调用我们的AudioCodec类的PlayAudio方法播放音频数据
    int samples_played = codec->PlayAudio(samples, sample_count);
    *bytes_written = samples_played * sizeof(int16_t);

    return ESP_OK;
}

// 音频播放器状态变化回调
static void audio_event_callback(audio_player_cb_ctx_t *ctx)
{
    if (!JiuchuangDevBoard::audio_board_instance)
        return;
    auto board = JiuchuangDevBoard::audio_board_instance;
    auto display = board->GetDisplay();
    switch (ctx->audio_event)
    {
    case AUDIO_PLAYER_CALLBACK_EVENT_PLAYING:
        ESP_LOGI(TAG, "音频播放中...");
        // 获取当前播放的文件名
        if (!board->current_file.empty()) {
            size_t pos = board->current_file.find_last_of("/\\");
            std::string filename = (pos != std::string::npos) ? board->current_file.substr(pos + 1) : board->current_file;
            std::string displayName = process_sd_filename(filename.c_str());
            std::string status_text = "正在播放: " + displayName;
            display->SetStatus(status_text.c_str());
            display->SetChatMessage("system", status_text.c_str());
        } else {
        display->SetStatus("正在播放音乐");
        }
        display->SetEmotion("happy");
        break;
    case AUDIO_PLAYER_CALLBACK_EVENT_PAUSE:
        ESP_LOGI(TAG, "音频已暂停");
        display->SetStatus("音乐已暂停");
        break;
    case AUDIO_PLAYER_CALLBACK_EVENT_IDLE:
        ESP_LOGI(TAG, "音频播放结束");
        
        // 检查是否正在切换中，如果是则不自动播放下一首
        if (board->is_switching) {
            ESP_LOGI(TAG, "正在切换中，不自动播放下一首");
            break;
        }
        
        // 只有在用户仍处于音乐播放模式时才自动播放下一首
        if (board->IsPlaying()) {
            // 延迟一小段时间后自动播放下一首
            vTaskDelay(pdMS_TO_TICKS(100));
                        
            // 再次检查是否仍处于播放模式和切换状态
            if (board->IsPlaying() && !board->is_switching) {
                ESP_LOGI(TAG, "自动播放下一首歌曲");
                board->PlayNextSong();
            } else {
                ESP_LOGI(TAG, "播放模式已退出或正在切换，不自动播放下一首");
            }
        } else {
            ESP_LOGI(TAG, "当前不处于音乐播放模式，不自动播放下一首");
        }
        break;
    case AUDIO_PLAYER_CALLBACK_EVENT_COMPLETED_PLAYING_NEXT:
        break;
    case AUDIO_PLAYER_CALLBACK_EVENT_UNKNOWN_FILE_TYPE:
        ESP_LOGE(TAG, "未知文件类型");
        display->SetStatus("未知文件类型");
        break;
    default:
        ESP_LOGI(TAG, "音频事件: %d", ctx->audio_event);
        break;
    }
}

static esp_err_t restore_device_status()


























{
    if (!JiuchuangDevBoard::audio_board_instance)
        return ESP_ERR_INVALID_STATE;
    ESP_LOGI(TAG, "开始恢复设备状态");
        
    // 停止正在播放的音频
    ESP_LOGI(TAG, "停止音频播放");
    audio_player_stop();
        
    // 等待确保音频停止完成
    vTaskDelay(pdMS_TO_TICKS(100));
        
    auto& board = *JiuchuangDevBoard::audio_board_instance;
        
    // 强制重置播放状态标志
    ESP_LOGI(TAG, "强制重置播放状态标志");
    board.SetPlaying(false);

    auto &app = Application::GetInstance();
        
    // 重新启用语音功能
    ESP_LOGI(TAG, "重新启用语音功能");
    app.EnableVoiceFeatures();
        
    // 强制设置为待机状态
    ESP_LOGI(TAG, "强制设置应用状态为待机");
    app.SetDeviceState(DeviceState::kDeviceStateIdle);
        
    // 重新配置音频编解码器
    ESP_LOGI(TAG, "重新配置音频编解码器");
    auto codec = board.GetAudioCodec();
    codec->SetSampleRate(24000, (int)1);
    codec->EnableOutput(false);
    codec->EnableInput(true);
        
    // 更新用户界面
    ESP_LOGI(TAG, "更新用户界面");
    auto display = board.GetDisplay();
    if (display) {
        display->SetStatus(Lang::Strings::STANDBY);
        display->SetEmotion("neutral");
    }
        
    ESP_LOGI(TAG, "设备状态已完全恢复到小智模式");
    return ESP_OK;
}

static void sd_card_detect_task(void *arg)
{
    esp_log_level_set("sdmmc_common", ESP_LOG_NONE); // 完全禁用SDMMC公共日志
    esp_log_level_set("vfs_fat_sdmmc", ESP_LOG_NONE);
    const char mount_point[] = "/sdcard";
    esp_err_t ret;
    JiuchuangDevBoard *board = (JiuchuangDevBoard *)arg;
    ESP_LOGI(TAG, "SD卡检测任务启动");

    // 配置挂载设置
    esp_vfs_fat_sdmmc_mount_config_t mount_config = {
        .format_if_mount_failed = false,
        .max_files = 16,                   // 增加最大文件数以支持更多文件
        .allocation_unit_size = 16 * 1024, 
    };
    
    // 设置文件系统字符编码为UTF-8
    // 注意: ESP32上的文件系统API可能没有直接支持设置UTF-8编码的方法
    // 我们尝试通过增加日志和调试来解决中文文件名问题

    while (1)
    {
        // 检查SD卡是否已挂载
        if (!board->card_mounted)
        {
            ESP_LOGI(TAG, "尝试挂载SD卡...");
            ret = esp_vfs_fat_sdmmc_mount(mount_point, &board->host, &board->slot_config, &mount_config, &board->card);
            if (ret == ESP_OK)
            {
                ESP_LOGI(TAG, "SD卡挂载成功");
                board->card_mounted = true;
                
                // 打印SD卡信息
                sdmmc_card_print_info(stdout, board->card);
                
                // 列出SD卡文件
                list_sd_card_files(mount_point);
        }
        else
        {
                ESP_LOGE(TAG, "SD卡挂载失败: %s", esp_err_to_name(ret));
            }
        }
            else
            {
            // 仅检查SD卡是否存在，不进行任何自动播放操作
            if (list_sd_card_files(mount_point) != ESP_OK)
                {
                ESP_LOGI(TAG, "SD卡已移除，执行卸载操作");
                        esp_vfs_fat_sdcard_unmount(mount_point, board->card);
                        board->card_mounted = false;
                
                // 如果当前正在播放，停止播放
                if (board->IsPlaying())
                {
                    ESP_LOGI(TAG, "SD卡已移除且正在播放，停止播放");
                    audio_player_stop();
                    board->SetPlaying(false);
                    
                    // 恢复正常模式
                    auto &app = Application::GetInstance();
                    app.EnableVoiceFeatures();
                    app.SetDeviceState(DeviceState::kDeviceStateIdle);
                    
                    // 更新显示
                    auto display = board->GetDisplay();
                    if (display) {
                        display->SetStatus(Lang::Strings::STANDBY);
                        display->SetEmotion("neutral");
                    }
                }
            }
        }
        vTaskDelay(pdMS_TO_TICKS(1000));
    }
}

DECLARE_BOARD(JiuchuangDevBoard);
