#include "data_storage.h"
#include "system_monitor.h"
#include <string.h>
#include <stdio.h>
#include <stdlib.h>

/**
  * @brief 初始化数据存储模块
  * @param handle: 数据存储句柄指针
  * @retval HAL_StatusTypeDef
  */
HAL_StatusTypeDef DataStorage_Init(DataStorageHandle_t *handle)
{
    if (handle == NULL) {
        return HAL_ERROR;
    }
    
    // 初始化句柄
    memset(handle, 0, sizeof(DataStorageHandle_t));
    
    // 初始化双缓冲区
    for (int i = 0; i < 2; i++) {
        handle->buffers[i].index = 0;
        handle->buffers[i].state = BUFFER_IDLE;
        memset(handle->buffers[i].data, 0, DATA_STORAGE_BUFFER_SIZE);
    }
    
    // 设置活动缓冲区为0
    handle->active_buffer = 0;
    handle->flush_buffer = 1;
    handle->flush_in_progress = 0;
    
    // 读取Flash计数器，计算本次会话起始值并立即写回
    // 策略：上电读取存储值+1000作为本次起始，立即写入，防止异常断电重复使用同一区间
    uint32_t flash_base = 0;
    FlashCounter_Init(&flash_base);
    handle->file_counter = flash_base + 1000;
    FlashCounter_Write(handle->file_counter);

    handle->stats.state = DATA_STORAGE_IDLE;
    handle->initialized = 1;

    return HAL_OK;
}

/**
  * @brief 停止数据记录
  * @param handle: 数据存储句柄指针
  * @retval HAL_StatusTypeDef
  */
HAL_StatusTypeDef DataStorage_StopRecording(DataStorageHandle_t *handle)
{
    if (handle == NULL || !handle->initialized) {
        return HAL_ERROR;
    }
    
    if (handle->stats.state != DATA_STORAGE_RECORDING) {
        return HAL_OK; // 没有在记录中
    }
    
    // 刷新所有缓冲区
    for (int i = 0; i < 2; i++) {
        if (handle->buffers[i].index > 0) {
            handle->buffers[i].state = BUFFER_READY_TO_FLUSH;
            DataStorage_FlushBuffer(handle, i);
        }
    }
    
    // 强制同步所有数据到SD卡
    f_sync(&handle->file);
    
    // 关闭文件
    f_close(&handle->file);
    
    handle->stats.state = DATA_STORAGE_IDLE;
    
    return HAL_OK;
}

/**
  * @brief 写入数据包到存储
  * @param handle: 数据存储句柄指针
  * @param packet: 数据包指针
  * @retval HAL_StatusTypeDef
  */
HAL_StatusTypeDef DataStorage_WriteData(DataStorageHandle_t *handle, const DataPacket_t *packet)
{
    if (handle == NULL || packet == NULL || !handle->initialized) {
        return HAL_ERROR;
    }
    
    if (handle->stats.state != DATA_STORAGE_RECORDING) {
        return HAL_ERROR;
    }
    
    DataBuffer_t *active_buf = &handle->buffers[handle->active_buffer];
    
    // 检查当前活动缓冲区空间
    if (active_buf->index + sizeof(DataPacket_t) > DATA_STORAGE_BUFFER_SIZE) {
        // 切换缓冲区
        if (DataStorage_SwitchBuffer(handle) != HAL_OK) {
            handle->stats.error_count++;
            return HAL_ERROR;
        }
        active_buf = &handle->buffers[handle->active_buffer];
    }
    
    // 复制数据到活动缓冲区
    memcpy(&active_buf->data[active_buf->index], packet, sizeof(DataPacket_t));
    active_buf->index += sizeof(DataPacket_t);
    active_buf->state = BUFFER_WRITING;
    handle->stats.total_samples++;
    
    return HAL_OK;
}

/**
  * @brief 通用字节流写入，支持任意包长度（方案Y混流存储）
  * @param handle: 数据存储句柄指针
  * @param data:   数据缓冲区指针
  * @param size:   写入字节数
  * @retval HAL_StatusTypeDef
  */
HAL_StatusTypeDef DataStorage_WriteRawBytes(DataStorageHandle_t *handle, const uint8_t *data, uint16_t size)
{
    if (handle == NULL || data == NULL || !handle->initialized || size == 0) {
        return HAL_ERROR;
    }

    if (handle->stats.state != DATA_STORAGE_RECORDING) {
        return HAL_ERROR;
    }

    DataBuffer_t *active_buf = &handle->buffers[handle->active_buffer];

    if (active_buf->index + size > DATA_STORAGE_BUFFER_SIZE) {
        if (DataStorage_SwitchBuffer(handle) != HAL_OK) {
            handle->stats.error_count++;
            return HAL_ERROR;
        }
        active_buf = &handle->buffers[handle->active_buffer];
    }

    memcpy(&active_buf->data[active_buf->index], data, size);
    active_buf->index += size;
    active_buf->state = BUFFER_WRITING;
    handle->stats.total_samples++;

    return HAL_OK;
}

/**
  * @brief 写入校正后的数据包到存储
  * @param handle: 数据存储句柄指针
  * @param packet: 数据包指针
  * @retval HAL_StatusTypeDef
  */
HAL_StatusTypeDef DataStorage_WriteCorrectedData(DataStorageHandle_t *handle, const CorrectedDataPacket_t *packet)
{
    if (handle == NULL || packet == NULL || !handle->initialized) {
        return HAL_ERROR;
    }
    
    if (handle->stats.state != DATA_STORAGE_RECORDING) {
        return HAL_ERROR;
    }
    
    DataBuffer_t *active_buf = &handle->buffers[handle->active_buffer];
    
    // 检查当前活动缓冲区空间
    if (active_buf->index + sizeof(CorrectedDataPacket_t) > DATA_STORAGE_BUFFER_SIZE) {
        // 切换缓冲区
        if (DataStorage_SwitchBuffer(handle) != HAL_OK) {
            handle->stats.error_count++;
            return HAL_ERROR;
        }
        active_buf = &handle->buffers[handle->active_buffer];
    }
    
    // 复制校正后的数据到活动缓冲区
    memcpy(&active_buf->data[active_buf->index], packet, sizeof(CorrectedDataPacket_t));
    active_buf->index += sizeof(CorrectedDataPacket_t);
    active_buf->state = BUFFER_WRITING;
    handle->stats.total_samples++;
    
    return HAL_OK;
}

/**
  * @brief 刷新缓冲区到文件
  * @param handle: 数据存储句柄指针
  * @retval HAL_StatusTypeDef
  */
HAL_StatusTypeDef DataStorage_Flush(DataStorageHandle_t *handle)
{
    if (handle == NULL || !handle->initialized) {
        return HAL_ERROR;
    }
    
    // 处理后台刷新任务
    DataStorage_ProcessBackgroundTasks(handle);
    
    return HAL_OK;
}

/**
  * @brief 创建新的数据文件
  * @param handle: 数据存储句柄指针
  * @retval HAL_StatusTypeDef
  */
HAL_StatusTypeDef DataStorage_CreateNewFile(DataStorageHandle_t *handle)
{
    if (handle == NULL || !handle->initialized) {
        return HAL_ERROR;
    }

    GPS_Data_t gps;
    GPS_GetData(&gps);

    if (gps.data_valid) {
        // GPS有效：用 HHMMSS 命名，同秒冲突时追加 _1 _2 ...
        char base[DATA_STORAGE_MAX_PATH_LEN];
        snprintf(base, sizeof(base), "%s/%02u%02u%02u",
                 handle->current_session_path,
                 gps.time.hour, gps.time.minute, gps.time.second);

        FILINFO fno;
        snprintf(handle->stats.current_filename,
                 sizeof(handle->stats.current_filename), "%s.dat", base);

        if (f_stat(handle->stats.current_filename, &fno) == FR_OK) {
            for (int i = 1; i <= 99; i++) {
                snprintf(handle->stats.current_filename,
                         sizeof(handle->stats.current_filename),
                         "%s_%d.dat", base, i);
                if (f_stat(handle->stats.current_filename, &fno) != FR_OK) break;
            }
        }
    } else {
        // 无GPS：用Flash计数器命名 C0001000.dat
        snprintf(handle->stats.current_filename,
                 sizeof(handle->stats.current_filename),
                 "%s/C%08lu.dat",
                 handle->current_session_path, handle->file_counter++);
    }

    FRESULT res = f_open(&handle->file, handle->stats.current_filename,
                         FA_CREATE_ALWAYS | FA_WRITE);
    if (res != FR_OK) {
        handle->stats.error_count++;
        SystemMonitor_ReportSDWriteError();
        return HAL_ERROR;
    }

    handle->stats.file_count++;
    handle->stats.current_file_size = 0;
    SystemMonitor_ReportSDFileCreated();

    return HAL_OK;
}

/**
  * @brief 获取数据存储统计信息
  * @param handle: 数据存储句柄指针
  * @param stats: 统计信息结构体指针
  * @retval None
  */
void DataStorage_GetStats(DataStorageHandle_t *handle, DataStorageStats_t *stats)
{
    if (handle == NULL || stats == NULL || !handle->initialized) {
        return;
    }
    
    memcpy(stats, &handle->stats, sizeof(DataStorageStats_t));
}

/**
  * @brief 开始数据记录
  * @param handle: 数据存储句柄指针
  * @retval HAL_StatusTypeDef
  */
HAL_StatusTypeDef DataStorage_StartRecording(DataStorageHandle_t *handle)
{
    if (handle == NULL || !handle->initialized) {
        return HAL_ERROR;
    }
    
    if (handle->stats.state == DATA_STORAGE_RECORDING) {
        return HAL_OK; // 已经在记录中
    }

    // 每次开始录制时确定会话目录（此时GPS可能已定位）
    if (DataStorage_CreateSessionFolder(handle) != HAL_OK) {
        handle->stats.state = DATA_STORAGE_ERROR;
        return HAL_ERROR;
    }

    // 创建新文件
    if (DataStorage_CreateNewFile(handle) != HAL_OK) {
        handle->stats.state = DATA_STORAGE_ERROR;
        return HAL_ERROR;
    }
    
    // 重置双缓冲区状态
    for (int i = 0; i < 2; i++) {
        handle->buffers[i].index = 0;
        handle->buffers[i].state = BUFFER_IDLE;
    }
    handle->active_buffer = 0;
    handle->flush_buffer = 1;
    handle->flush_in_progress = 0;
    
    handle->stats.state = DATA_STORAGE_RECORDING;
    
    return HAL_OK;
}

/**
  * @brief 刷新指定缓冲区到文件
  * @param handle: 数据存储句柄指针
  * @param buffer_index: 缓冲区索引 (0 或 1)
  * @retval HAL_StatusTypeDef
  */
HAL_StatusTypeDef DataStorage_FlushBuffer(DataStorageHandle_t *handle, uint8_t buffer_index)
{
    if (handle == NULL || !handle->initialized || buffer_index > 1) {
        return HAL_ERROR;
    }
    
    DataBuffer_t *buffer = &handle->buffers[buffer_index];
    
    // 检查缓冲区状态和数据
    if (buffer->state != BUFFER_READY_TO_FLUSH || buffer->index == 0) {
        return HAL_OK; // 没有数据需要刷新
    }
    
    // 标记缓冲区正在刷新
    buffer->state = BUFFER_FLUSHING;
    
    UINT bytes_written;
    FRESULT res = f_write(&handle->file, buffer->data, buffer->index, &bytes_written);
    
    if (res != FR_OK || bytes_written != buffer->index) {
        handle->stats.error_count++;
        buffer->state = BUFFER_READY_TO_FLUSH; // 恢复状态以便重试
        SystemMonitor_ReportSDWriteError();  // 报告SD卡写入错误
        return HAL_ERROR;
    }
    
    // 优化：减少同步频率以提高性能
    // 使用静态变量记录刷新次数
    static uint32_t flush_count = 0;
    flush_count++;
    
    // 每10次刷新才同步一次，或者文件即将达到最大大小时同步
    if (flush_count % 10 == 0 ||
        handle->stats.current_file_size + bytes_written >= DATA_STORAGE_FILE_MAX_SIZE) {
        f_sync(&handle->file);
    }
    
    // 更新统计信息
    handle->stats.current_file_size += bytes_written;
    SystemMonitor_ReportSDWrite(bytes_written);  // 报告SD卡写入成功
    
    // 重置缓冲区
    buffer->index = 0;
    buffer->state = BUFFER_IDLE;
    
    // 检查文件大小是否超过限制
    if (handle->stats.current_file_size >= DATA_STORAGE_FILE_MAX_SIZE) {
        f_close(&handle->file);
        DataStorage_CreateNewFile(handle);
    }
    
    return HAL_OK;
}

/**
  * @brief 处理后台任务（异步刷新缓冲区）
  * @param handle: 数据存储句柄指针
  * @retval None
  */
void DataStorage_ProcessBackgroundTasks(DataStorageHandle_t *handle)
{
    if (handle == NULL || !handle->initialized) {
        return;
    }
    
    // 检查是否有缓冲区需要刷新
    for (int i = 0; i < 2; i++) {
        if (handle->buffers[i].state == BUFFER_READY_TO_FLUSH) {
            // 刷新缓冲区
            DataStorage_FlushBuffer(handle, i);
            break; // 一次只处理一个缓冲区，避免阻塞太久
        }
    }
}

/**
  * @brief 切换活动缓冲区
  * @param handle: 数据存储句柄指针
  * @retval HAL_StatusTypeDef
  */
HAL_StatusTypeDef DataStorage_SwitchBuffer(DataStorageHandle_t *handle)
{
    if (handle == NULL || !handle->initialized) {
        return HAL_ERROR;
    }
    
    DataBuffer_t *current_buf = &handle->buffers[handle->active_buffer];
    
    // 标记当前缓冲区准备刷新
    if (current_buf->index > 0) {
        current_buf->state = BUFFER_READY_TO_FLUSH;
    }
    
    // 切换到另一个缓冲区
    uint8_t next_buffer = (handle->active_buffer == 0) ? 1 : 0;
    DataBuffer_t *next_buf = &handle->buffers[next_buffer];
    
    // 检查目标缓冲区是否可用
    if (next_buf->state == BUFFER_FLUSHING) {
        // 目标缓冲区正在刷新，等待完成
        handle->stats.error_count++;
        SystemMonitor_ReportSDBufferFull();  // 报告缓冲区满
        return HAL_ERROR;
    }
    
    // 切换活动缓冲区
    handle->active_buffer = next_buffer;
    next_buf->index = 0;
    next_buf->state = BUFFER_WRITING;
    
    return HAL_OK;
}

/**
  * @brief 检查缓冲区是否有足够空间可用
  * @param handle: 数据存储句柄指针
  * @param required_size: 需要的空间大小（字节）
  * @retval 1: 缓冲区可用, 0: 缓冲区不可用
  */
uint8_t DataStorage_IsBufferAvailable(DataStorageHandle_t *handle, uint32_t required_size)
{
    if (handle == NULL || !handle->initialized) {
        return 0;
    }
    
    // 如果未在记录状态，返回不可用
    if (handle->stats.state != DATA_STORAGE_RECORDING) {
        return 0;
    }
    
    DataBuffer_t *active_buf = &handle->buffers[handle->active_buffer];
    
    // 检查当前活动缓冲区是否有足够空间
    if (active_buf->index + required_size <= DATA_STORAGE_BUFFER_SIZE) {
        return 1; // 当前缓冲区有足够空间
    }
    
    // 当前缓冲区空间不足，检查是否可以切换到另一个缓冲区
    uint8_t next_buffer = (handle->active_buffer == 0) ? 1 : 0;
    DataBuffer_t *next_buf = &handle->buffers[next_buffer];
    
    // 如果另一个缓冲区正在刷新或准备刷新，则不可用
    if (next_buf->state == BUFFER_FLUSHING || next_buf->state == BUFFER_READY_TO_FLUSH) {
        return 0; // 无法切换，缓冲区不可用
    }
    
    // 另一个缓冲区可用
    return 1;
}

/**
  * @brief 创建新的会话文件夹
  * @param handle: 数据存储句柄指针
  * @retval HAL_StatusTypeDef
  */
HAL_StatusTypeDef DataStorage_CreateSessionFolder(DataStorageHandle_t *handle)
{
    if (handle == NULL) {
        return HAL_ERROR;
    }

    // 创建基础数据目录
    FRESULT res = f_mkdir(DATA_STORAGE_BASE_PATH);
    if (res != FR_OK && res != FR_EXIST) {
        return HAL_ERROR;
    }

    GPS_Data_t gps;
    GPS_GetData(&gps);

    if (gps.date_valid) {
        // GPS日期有效：目录格式 0:/DATA/YYYYMMDD
        snprintf(handle->current_session_path, sizeof(handle->current_session_path),
                 "%s/%04u%02u%02u",
                 DATA_STORAGE_BASE_PATH,
                 gps.date.year, gps.date.month, gps.date.day);
    } else {
        // 无GPS日期：统一放入 NOFX 目录
        snprintf(handle->current_session_path, sizeof(handle->current_session_path),
                 "%s", DATA_STORAGE_NOFX_DIR);
    }

    res = f_mkdir(handle->current_session_path);
    if (res != FR_OK && res != FR_EXIST) {
        return HAL_ERROR;
    }

    return HAL_OK;
}

