#include "ff.h"
#include "stdio.h"
#include "string.h"
#include "main.h" // Ensure huart3 is defined here

//#define NEED_FORMAT_SD
#ifdef NEED_FORMAT_SD

extern UART_HandleTypeDef huart3;

// Configuration
#define TEST_FILE_NAME    "ST_DATA.BIN"
#define TEST_BUF_SIZE     (64 * 1024)       // 64KB Buffer (Good for SDIO DMA)
#define TOTAL_TEST_SIZE   (16 * 1024 * 1024) // 16MB Total Data

// Align buffer to 4 bytes for DMA compatibility
uint8_t g_test_buffer[TEST_BUF_SIZE] __attribute__((aligned(4)));
char uart_buf[128]; // Buffer for formatting UART messages

// Helper function to print via UART3
void UART3_Print(const char* str) {
    HAL_UART_Transmit(&huart3, (uint8_t*)str, strlen(str), 100);
}

void Run_SDNAND_SpeedTest(void) {
    FIL file;
    FRESULT res;
    UINT bw, br;
    uint32_t startTime, endTime;
    float speed;

    UART3_Print("\r\n=== SD NAND Speed Test Start ===\r\n");
    
    // Initialize buffer with dummy data
    for (uint32_t i = 0; i < TEST_BUF_SIZE; i++) g_test_buffer[i] = (uint8_t)(i % 256);

    // --- WRITE TEST ---
    res = f_open(&file, TEST_FILE_NAME, FA_CREATE_ALWAYS | FA_WRITE);
    if (res != FR_OK) {
        sprintf(uart_buf, "Open Fail (Write). Error: %d\r\n", res);
        UART3_Print(uart_buf);
        return;
    }

    UART3_Print("Testing Write Speed... Please wait.\r\n");
    startTime = HAL_GetTick();
    for (uint32_t i = 0; i < TOTAL_TEST_SIZE / TEST_BUF_SIZE; i++) {
        res = f_write(&file, g_test_buffer, TEST_BUF_SIZE, &bw);
        if (res != FR_OK) break;
    }
    f_sync(&file); // Flush to physical NAND
    endTime = HAL_GetTick();

    speed = ((float)TOTAL_TEST_SIZE / 1024.0 / 1024.0) / ((float)(endTime - startTime) / 1000.0);
    sprintf(uart_buf, "WRITE: %.2f MB/s (%lu ms)\r\n", speed, endTime - startTime);
    UART3_Print(uart_buf);
    f_close(&file);

    // --- READ TEST ---
    res = f_open(&file, TEST_FILE_NAME, FA_READ);
    if (res != FR_OK) {
        UART3_Print("Open Fail (Read)\r\n");
        return;
    }

    UART3_Print("Testing Read Speed... Please wait.\r\n");
    startTime = HAL_GetTick();
    for (uint32_t i = 0; i < TOTAL_TEST_SIZE / TEST_BUF_SIZE; i++) {
        res = f_read(&file, g_test_buffer, TEST_BUF_SIZE, &br);
        if (res != FR_OK) break;
    }
    endTime = HAL_GetTick();

    speed = ((float)TOTAL_TEST_SIZE / 1024.0 / 1024.0) / ((float)(endTime - startTime) / 1000.0);
    sprintf(uart_buf, "READ:  %.2f MB/s (%lu ms)\r\n", speed, endTime - startTime);
    UART3_Print(uart_buf);

    f_close(&file);
    f_unlink(TEST_FILE_NAME); // Clean up
    UART3_Print("=== Test Finished ===\r\n");
}

extern SD_HandleTypeDef hsd;
extern DMA_HandleTypeDef hdma_sdio_rx;
extern DMA_HandleTypeDef hdma_sdio_tx;

void Raw_Hardware_Test(void) {
    uint32_t start, end;
    HAL_StatusTypeDef status;

    UART3_Print("\r\n--- Starting Raw Hardware Test (No File System) ---\r\n");

    // Test Raw DMA Write
    start = HAL_GetTick();
    status = HAL_SD_WriteBlocks_DMA(&hsd, g_test_buffer, 1000, TEST_BUF_SIZE / 512);
    if (status == HAL_OK) {
        // Wait for DMA to finish
        while (HAL_SD_GetCardState(&hsd) != HAL_SD_CARD_TRANSFER) {}
        end = HAL_GetTick();
        sprintf(uart_buf, "Raw DMA Write: %lu ms\r\n", end - start);
        UART3_Print(uart_buf);
    } else {
        UART3_Print("Raw Write Failed!\r\n");
    }
}

void Run_SDNAND_SpeedTest_V2(void) {
    FIL file;
    FRESULT res;
    UINT bw, br;
    uint32_t startTime, endTime, duration;
    float speed;

    UART3_Print("\r\n=== SD NAND Speed Test V2 ===\r\n");

    // 预填充数据
    for (uint32_t i = 0; i < TEST_BUF_SIZE; i++) g_test_buffer[i] = (uint8_t)(i % 256);

    // --- WRITE TEST ---
    res = f_open(&file, TEST_FILE_NAME, FA_CREATE_ALWAYS | FA_WRITE);
    if (res != FR_OK) {
        sprintf(uart_buf, "Open Fail (Write). Error: %d\r\n", res);
        UART3_Print(uart_buf);
        return;
    }

    UART3_Print("Writing 16MB...\r\n");
    startTime = HAL_GetTick();

    for (uint32_t i = 0; i < TOTAL_TEST_SIZE / TEST_BUF_SIZE; i++) {
        res = f_write(&file, g_test_buffer, TEST_BUF_SIZE, &bw);
        if (res != FR_OK || bw != TEST_BUF_SIZE) {
            sprintf(uart_buf, "Write Fail at block %lu, Res: %d\r\n", i, res);
            UART3_Print(uart_buf);
            f_close(&file);
            return;
        }
    }

    f_close(&file); // 必须先关闭文件，确保 FAT 目录项更新
    endTime = HAL_GetTick();
    duration = (endTime - startTime > 0) ? (endTime - startTime) : 1; // 防止除以0

    speed = ((float)TOTAL_TEST_SIZE / 1024.0 / 1024.0) / ((float)duration / 1000.0);
    sprintf(uart_buf, "WRITE Result: %.2f MB/s (%lu ms)\r\n", speed, duration);
    UART3_Print(uart_buf);

    // --- READ TEST ---
    HAL_Delay(100); // 稍微等待文件系统稳定
    res = f_open(&file, TEST_FILE_NAME, FA_READ);
    if (res != FR_OK) {
        sprintf(uart_buf, "Open Fail (Read). Error: %d\r\n", res);
        UART3_Print(uart_buf);
        return;
    }

    UART3_Print("Reading 16MB...\r\n");
    startTime = HAL_GetTick();
    for (uint32_t i = 0; i < TOTAL_TEST_SIZE / TEST_BUF_SIZE; i++) {
        res = f_read(&file, g_test_buffer, TEST_BUF_SIZE, &br);
        if (res != FR_OK || br != TEST_BUF_SIZE) {
            sprintf(uart_buf, "Read Fail at block %lu, Res: %d\r\n", i, res);
            UART3_Print(uart_buf);
            break;
        }
    }
    endTime = HAL_GetTick();
    duration = (endTime - startTime > 0) ? (endTime - startTime) : 1;

    speed = ((float)TOTAL_TEST_SIZE / 1024.0 / 1024.0) / ((float)duration / 1000.0);
    sprintf(uart_buf, "READ Result:  %.2f MB/s (%lu ms)\r\n", speed, duration);
    UART3_Print(uart_buf);

    f_close(&file);
    UART3_Print("=== Test Finished ===\r\n");
}

void SDNAND_ForceFormat_and_Mount(void) {
    FATFS fs;
    FRESULT res;
    BYTE work[_MAX_SS];
    char msg[128];

    UART3_Print("\r\n--- Initializing SD NAND for Optimization ---\r\n");

    // 1. 先尝试挂载 (立即挂载模式)
    res = f_mount(&fs, "", 1);
    if (res != FR_OK && res != FR_NO_FILESYSTEM) {
        sprintf(msg, "Mount failed before format: %d\r\n", res);
        UART3_Print(msg);
        return;
    }

    // 2. 执行格式化 (强制 512 簇)
    UART3_Print("Formatting... this may take a few seconds.\r\n");
    res = f_mkfs("", FM_FAT32, 32768, work, sizeof(work));
    if (res != FR_OK) {
        sprintf(msg, "Format failed: %d\r\n", res);
        UART3_Print(msg);
        return;
    }
    UART3_Print("Format completed successfully.\r\n");

    // 3. 卸载以清除旧缓存
    f_mount(NULL, "", 0);

    // 4. 重新挂载
    res = f_mount(&fs, "", 1);
    if (res == FR_OK) {
        UART3_Print("SD NAND Remounted with 4KB cluster size.\r\n");
    } else {
        sprintf(msg, "Final mount failed: %d\r\n", res);
        UART3_Print(msg);
    }
}

#endif
