#include "system/app_core.h"
#include "os/os_api.h"
#include "app_config.h"
#include "event/key_event.h"
#include "system/includes.h"
#include "wifi/wifi_connect.h"
#include "http/http_cli.h"
#include "fs/fs.h"
#include <curl/curl.h>

#define BUFFER_SIZE 16 * 1024
#define HTTP_DEMO_URL "http://180.101.51.191/process_audio/"
#define REQ_FILE            CONFIG_ROOT_PATH"INTERACT/req."CONFIG_AUDIO_RECORDER_SAVE_FORMAT
#define RES_FILE            CONFIG_ROOT_PATH"INTERACT/res."CONFIG_AUDIO_RECORDER_SAVE_FORMAT

#define READ_BUFFER_SIZE 4 * 1024  // 20 KB

// 回调函数，用于打印请求头
size_t curl_header_cb(char *buffer, size_t size, size_t nitems, void *userdata) {
    size_t total_size = size * nitems;
    printf("-----------Header: %.*s\n", (int)total_size, buffer);
    return total_size;
}

// 读取回调函数
size_t curl_read_cb(void *ptr, size_t size, size_t nmemb, FILE *stream) {
    printf("----------Entering read_callback\n"); // 确认回调是否被调用
    size_t max_read = READ_BUFFER_SIZE < size * nmemb ? READ_BUFFER_SIZE : size * nmemb;
    printf("----------read data: %d\n", max_read);
    return fread(ptr, 1, max_read, stream);
}

// 回调函数，用于处理服务器的响应数据
size_t curl_write_cb1(void *ptr, size_t size, size_t nmemb, FILE *stream) {
    size_t total_size = size * nmemb;
    size_t written = 0;

    // 动态分配缓冲区
    char *buffer = (char *)malloc(BUFFER_SIZE);
    if (!buffer) {
        printf("Failed to allocate memory for buffer\n");
        return 0;  // 返回0表示错误
    }

    // 确定要写入的大小
    size_t to_write = (total_size > BUFFER_SIZE) ? BUFFER_SIZE : total_size;

    // 复制数据到缓冲区
    memcpy(buffer, ptr, to_write);

    // 写入文件
    written = fwrite(buffer, 1, to_write, stream);

    // 释放缓冲区
    free(buffer);
    printf("----------save data: %d\n", to_write);
    
    return written;  // 返回实际写入的字节数
}

static void http_test_task(void *priv) {
    CURL *curl = NULL;
    CURLcode res = CURLE_OK;
    curl_mime *mime = NULL;
    curl_mimepart *part = NULL;
    // struct curl_httppost *formpost = NULL;
    // struct curl_httppost *lastptr = NULL;
    // const char *file_to_upload = CONFIG_STORAGE_PATH"/C/input.mp3"; // 要上传的文件名
    // const char *output_file = CONFIG_STORAGE_PATH"/C/output.mp3"; // 保存返回的文件名

    // 打开要上传的文件
    FILE *file = fopen(REQ_FILE, "rb");
    if (!file) {
        perror("Failed to open input file");
        return;
    }
    fclose(file);

    // fseek(file, 0, SEEK_END);
    // long file_size = ftell(file);
    // fseek(file, 0, SEEK_SET);
    // printf("File size: %ld bytes\n", file_size);

    // 初始化libcurl
    curl_global_init(CURL_GLOBAL_ALL);
    curl = curl_easy_init();

    if (curl) {
        // 设置URL
        curl_easy_setopt(curl, CURLOPT_URL, HTTP_DEMO_URL);

        // curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L); // 设置为上传模式
        
        // 允许重定向
        curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
        // curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);

        // // 设置Expect: 100-continue
        // struct curl_slist *headers = NULL;
        // headers = curl_slist_append(headers, "Expect: 100-continue");
        // curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
        
        // // 设置表单数据
        // CURLFORMcode result = curl_formadd(&formpost, &lastptr,
        //         CURLFORM_COPYNAME, "input_file", // 确保字段名正确
        //         CURLFORM_FILE, file_to_upload,
        //         CURLFORM_END);

        // if (result != CURL_FORMADD_OK) {
        //     printf("----------Error adding form data: %d\n", result);
        //     return;
        // }
        
        // // 设置表单数据
        // // 设置表单数据并检查
        // res = curl_easy_setopt(curl, CURLOPT_HTTPPOST, formpost);
        // if (res != CURLE_OK) {
        //     printf("Failed to set HTTPPOST: %s\n", curl_easy_strerror(res));
        //     return;
        // }
        // curl_easy_setopt(curl, CURLOPT_HTTPPOST, formpost);

        // 创建 MIME 数据
        mime = curl_mime_init(curl);
        part = curl_mime_addpart(mime);
        curl_mime_name(part, "input_file");
        curl_mime_filedata(part, REQ_FILE);

        curl_easy_setopt(curl, CURLOPT_MIMEPOST, mime);

        // 设置回调函数以打印请求头
        curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, curl_header_cb);
        curl_easy_setopt(curl, CURLOPT_HEADERDATA, NULL);

        // 设置回调函数
        curl_easy_setopt(curl, CURLOPT_READFUNCTION, curl_read_cb);
        curl_easy_setopt(curl, CURLOPT_READDATA, file);
        
        // 设置回调函数处理响应
        FILE *response_file = fopen(RES_FILE, "wb");
        if (!response_file) {
            perror("Failed to open output file");
            // fclose(file);
            return;
        }
        
        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, curl_write_cb1);
        curl_easy_setopt(curl, CURLOPT_WRITEDATA, response_file);

        // 设置超时时间
        curl_easy_setopt(curl, CURLOPT_TIMEOUT, 30L); // 总超时30秒
        curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 10L); // 连接超时10秒

        printf("----------start do curl\n");
        
        // 执行请求
        res = curl_easy_perform(curl);
        
        // 检查请求结果
        if(res != CURLE_OK) {
            printf("curl_easy_perform() failed: %s\n", curl_easy_strerror(res));
        } else {
            long http_code = 0;
            curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_code);
            if(http_code != 200) {
                printf("Upload failed with HTTP status code: %ld\n", http_code);
            } else {
                printf("Request succeeded, response saved to %s\n", RES_FILE);
            }
        }

        // 清理
        fclose(response_file);
        // curl_slist_free_all(headers);
        // curl_formfree(formpost); // 释放表单数据
        curl_mime_free(mime); // 释放 MIME 数据
        curl_easy_cleanup(curl);
    }

    curl_global_cleanup();
    // fclose(file);
    printf("------end post----");
}

static void http_user_header_test(void *priv)
{
    //等待获取ip成功
    enum wifi_sta_connect_state state;
    while (1) {
        printf("Connecting to the network...\n");
        state = wifi_get_sta_connect_state();
        if (WIFI_STA_NETWORK_STACK_DHCP_SUCC == state) {
            printf("Network connection is successful!\n");
            break;
        }
        os_time_dly(100);
    }

    //等待存储设备就绪
    while (1) {
        if (!storage_device_ready()) {
            printf("Wait for the storage device to be ready !");
            os_time_dly(10);
            continue;
        }
        printf("the storage device is ready!");
        break;
    }

    if (thread_fork("http_test_task", 10, 4 * 1024, 0, NULL, http_test_task, NULL) != OS_NO_ERR) {
        printf("thread fork fail\n");
    }
}

static int upload_mode_init(void)
{
    log_i("upload_play_main\n");

    return 0;
}

static void upload_mode_exit(void)
{
    return;
}

static int upload_key_click(struct key_event *key)
{
    int ret = true;

    printf("upload ---> key value: %d <---", key->value);

    switch (key->value) {
    case KEY_OK:
        if (thread_fork("http_user_header_test", 10, 512, 0, NULL, http_user_header_test, NULL) != OS_NO_ERR) {
            printf("thread fork fail\n");
        }
        break;
    default:
        ret = false;
        break;
    }

    return ret;
}

static int upload_key_long(struct key_event *key)
{
    return true;
}

static int upload_key_event_handler(struct key_event *key)
{
    switch (key->action) {
    case KEY_EVENT_CLICK:
        return upload_key_click(key);
    case KEY_EVENT_LONG:
        return upload_key_long(key);
    default:
        break;
    }

    return true;
}

static int upload_event_handler(struct application *app, struct sys_event *event)
{
    switch (event->type) {
    case SYS_KEY_EVENT:
        return upload_key_event_handler((struct key_event *)event->payload);
    default:
        return false;
    }
}

static int upload_state_machine(struct application *app, enum app_state state, struct intent *it)
{
    switch (state) {
    case APP_STA_CREATE:
        break;
    case APP_STA_START:
        upload_mode_init();
        break;
    case APP_STA_PAUSE:
        break;
    case APP_STA_RESUME:
        break;
    case APP_STA_STOP:
        upload_mode_exit();
        break;
    case APP_STA_DESTROY:
        break;
    }

    return 0;
}

static const struct application_operation upload_ops = {
    .state_machine  = upload_state_machine,
    .event_handler 	= upload_event_handler,
};

REGISTER_APPLICATION(upload) = {
    .name 	= "upload",
    .ops 	= &upload_ops,
    .state  = APP_STA_DESTROY,
};