#include "spiffs.h"

static const char *TAG = "SPIFFS";

/**
 * @brief 初始化并挂载 SPIFFS 文件系统
 * @param base_path 挂载点路径（如 "/spiffs"）
 * @return esp_err_t ESP_OK 成功，其他失败
 */
esp_err_t spiffs_init(const char *base_path)
{
    ESP_LOGI(TAG, "正在初始化 SPIFFS...");

    esp_vfs_spiffs_conf_t conf = {
        .base_path = base_path,
        .partition_label = NULL,       // 使用第一个找到的 SPIFFS 分区
        .max_files = 10,               // 最大打开文件数
        .format_if_mount_failed = true // 如果挂载失败则格式化
    };

    // 挂载 SPIFFS 分区
    esp_err_t ret = esp_vfs_spiffs_register(&conf);
    if (ret != ESP_OK)
    {
        if (ret == ESP_FAIL)
        {
            ESP_LOGE(TAG, "挂载 SPIFFS 失败");
        }
        else if (ret == ESP_ERR_NOT_FOUND)
        {
            ESP_LOGE(TAG, "未找到 SPIFFS 分区");
        }
        else
        {
            ESP_LOGE(TAG, "SPIFFS 初始化失败 (%s)", esp_err_to_name(ret));
        }
        return ret;
    }

    ESP_LOGI(TAG, "SPIFFS 挂载成功，挂载点: %s", base_path);

    // 获取分区信息
    size_t total = 0, used = 0;
    ret = esp_spiffs_info(NULL, &total, &used);
    if (ret != ESP_OK)
    {
        ESP_LOGE(TAG, "获取 SPIFFS 分区信息失败 (%s)", esp_err_to_name(ret));
    }
    else
    {
        ESP_LOGI(TAG, "分区大小: 总共 %d KB, 已用 %d KB, 可用 %d KB",
                 total / 1024, used / 1024, (total - used) / 1024);
    }

    return ESP_OK;
}

/**
 * @brief 列出 SPIFFS 文件（安全版本）
 */
void list_spiffs_files_safe(const char *base_path)
{
    ESP_LOGI(TAG, "Listing files in %s:", base_path);
    
    DIR *dir = opendir(base_path);
    if (dir == NULL) {
        ESP_LOGE(TAG, "Failed to open directory %s: %s", 
                base_path, strerror(errno));
        return;
    }
    
    struct dirent *entry;
    int count = 0;
    
    while ((entry = readdir(dir)) != NULL) {
        // 跳过 "." 和 ".."
        if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) {
            continue;
        }
        
        // 方法1：使用固定大小缓冲区（512字节足够）
        char full_path[512];
        int ret = snprintf(full_path, sizeof(full_path), "%s/%s", base_path, entry->d_name);
        
        if (ret < 0) {
            ESP_LOGW(TAG, "Error formatting path for: %s", entry->d_name);
            continue;
        }
        
        if ((size_t)ret >= sizeof(full_path)) {
            ESP_LOGW(TAG, "Path truncated for: %s", entry->d_name);
            // 继续处理，但路径可能不完整
        }
        
        // 方法2：使用动态分配（如果文件名可能很长）
        // size_t path_len = strlen(base_path) + 1 + strlen(entry->d_name) + 1;
        // char *full_path = malloc(path_len);
        // if (full_path) {
        //     snprintf(full_path, path_len, "%s/%s", base_path, entry->d_name);
        //     // ... 使用 full_path
        //     free(full_path);
        // }
        
        struct stat entry_stat;
        if (stat(full_path, &entry_stat) == -1) {
            ESP_LOGW(TAG, "  %s - cannot stat: %s", 
                    entry->d_name, strerror(errno));
            continue;
        }
        
        if (S_ISDIR(entry_stat.st_mode)) {
            ESP_LOGI(TAG, "  [DIR]  %-32s", entry->d_name);
        } else {
            const char *unit = "B";
            double size = (double)entry_stat.st_size;
            
            if (size >= 1024.0 * 1024.0) {
                size /= 1024.0 * 1024.0;
                unit = "MB";
            } else if (size >= 1024.0) {
                size /= 1024.0;
                unit = "KB";
            }
            
            ESP_LOGI(TAG, "  [FILE] %-32s %8.2f %s", 
                    entry->d_name, size, unit);
        }
        count++;
    }
    
    closedir(dir);
    
    if (count == 0) {
        ESP_LOGI(TAG, "  No files found");
    } else {
        ESP_LOGI(TAG, "Total: %d items", count);
    }
}