#include "audiotts_play.h"
#include "audioplay.h"
#include "device_identity.h"
#include "mqtt_init.h"
#include "http_config_mqtt.h"

#include <openssl/bio.h>
#include <openssl/evp.h>
#include <openssl/buffer.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <errno.h>

#define TTS_ADUINO_PTAH PROJECT_ROOT_DIR "/audio.mp3"

// 全局变量：存储 HTTP 响应数据
static char *s_http_response = NULL;
static size_t s_http_response_len = 0;

static bool s_audio_tts_index=0;

static double s_volume=1.0;


// HTTP 响应回调函数：接收服务器返回的 JSON 数据
static size_t http_write_callback(void *ptr, size_t size, size_t nmemb, void *userdata) {
    size_t total = size * nmemb;
    // 扩容并拷贝响应数据
    char *temp = realloc(s_http_response, s_http_response_len + total + 1);
    if (!temp) {
        my_zlog_error("Realloc response buffer failed");
        return 0;
    }
    s_http_response = temp;
    memcpy(s_http_response + s_http_response_len, ptr, total);
    s_http_response_len += total;
    s_http_response[s_http_response_len] = '\0';  // 末尾加结束符
    return total;
}

// 生成 UUID（去除连字符，保证 reqid 唯一性）
static void generate_uuid(char *buf, size_t len) {
    if (len < 33) return;  // UUID 去除连字符后 32 位
    uuid_t uuid;
    uuid_generate_random(uuid);
    uuid_unparse(uuid, buf);
    // 移除连字符
    char *p = strchr(buf, '-');
    while (p) {
        memmove(p, p + 1, strlen(p));
        p = strchr(buf, '-');
    }
}

// Base64 解码（将响应中的音频数据解码为二进制）
static unsigned char *base64_decode(const char *input, size_t *output_len) {
    BIO *bio, *b64;
    size_t len = strlen(input);
    unsigned char *buffer = (unsigned char *)malloc(len * 3 / 4 + 1024);  // 预留足够空间

    if (!buffer) return NULL;

    // 初始化 OpenSSL Base64 解码
    OpenSSL_add_all_algorithms();  // 初始化 OpenSSL 算法（避免解码失败）
    b64 = BIO_new(BIO_f_base64());
    bio = BIO_new_mem_buf(input, len);
    bio = BIO_push(b64, bio);

    // 禁用换行符处理（关键：避免 Base64 字符串含换行导致解码失败）
    BIO_set_flags(bio, BIO_FLAGS_BASE64_NO_NL);
    *output_len = BIO_read(bio, buffer, len * 3 / 4 + 1024);

    // 清理资源
    BIO_free_all(bio);

    // 调整缓冲区大小为实际解码长度
    buffer = realloc(buffer, *output_len);
    return buffer;
}


/**
 * 保存音频数据到文件（目录已存在）
 * @param data     音频数据指针
 * @param len      音频数据长度
 * @param filepath 完整文件路径
 * @return 0成功，1失败
 */
static int save_audio_file(const void *data, size_t len, const char *filepath) {
    if (!data || len == 0 || !filepath) {
        my_zlog_error("Invalid parameters for save_audio_file\n");
        return 1;
    }
    
    FILE *fp = fopen(filepath, "wb");
    if (!fp) {
        my_zlog_error( "Open file %s failed: %s\n", filepath, strerror(errno));
        return 1;
    }
    
    size_t written = fwrite(data, 1, len, fp);
    fclose(fp);
    
    if (written != len) {
        my_zlog_error("Write file %s incomplete: %zu/%zu bytes", filepath, written, len);
        remove(filepath); // 删除不完整的文件
        return 1;
    }
    
    my_zlog_debug("Success! Audio saved to: %s (%zu bytes)", filepath, written);
    return 0;
}

/*
*功能：获得随机字符串，不使用uuid
*/
static char* generate_random_string() {
    // 设置随机种子（建议在main函数中调用一次即可）
    static int seeded = 0;
    if (!seeded) {
        srand((unsigned int)time(NULL));
        seeded = 1;
    }

    // 动态分配内存（10个字符 + 终止符）
    char* str = (char*)malloc(11 * sizeof(char));
    if (!str) return NULL;

    // 生成数字字符（ASCII 48-57）
    for (int i = 0; i < 10; i++) {
        str[i] = '0' + (rand() % 10);
    }
    str[10] = '\0'; // 添加终止符
    return str;
}

char *get_audio_text_tts(char *date ,bool flag){

    static char text[256] = {0};  
    if(flag==1){
        return text;
    }else {
        size_t date_len = strlen(date);
         if (date) {
            strcpy(text, date);
            text[date_len] = '\0';  // 确保以null结尾
        } else {
            text[0] = '\0';  // 如果date为NULL，清空文本
        }
    }
}

/**
 * 保存音频数据到文件（目录已存在）
 * @param text     传入需要转化的文字指针
 * @return 0成功，1失败
 */
int audio_tts(const char *text) {
    
    // 1. 配置参数（替换为你的真实信息，已验证有效）
    const char *appid = "5745089507";          // 你的火山引擎 AppID
    const char *access_token = "0BeoBb_DOjrxfM4aTsJfUFVVS0k5V9mt";  // 你的访问令牌
    const char *voice_type = "zh_female_linjianvhai_moon_bigtts";  // 非流式音色
    const char *cluster = "volcano_tts";       // 固定值（必选）
    char *uid = generate_random_string();            // 任意非空字符串
    const char *encoding = "mp3";              // 输出格式（mp3/wav/pcm/ogg_opus）
    const char *endpoint = "https://openspeech.bytedance.com/api/v1/tts";  // HTTP 接口地址

    // 2. 生成唯一 reqid（每次调用必须不同）
    char reqid[33] = {0};
    generate_uuid(reqid, sizeof(reqid));
    my_zlog_debug("Generated ReqID: %s", reqid);

    // 3. 构建请求 JSON（严格遵循接口参数格式）
    cJSON *root = cJSON_CreateObject();
    if (!root) {
        my_zlog_error("Create JSON root failed");
        free(uid);
        return 1;
    }

    // app 节点（必选）
    cJSON *app = cJSON_CreateObject();
    cJSON_AddStringToObject(app, "appid", appid);
    cJSON_AddStringToObject(app, "token", access_token);
    cJSON_AddStringToObject(app, "cluster", cluster);
    cJSON_AddItemToObject(root, "app", app);

    // user 节点（必选）
    cJSON *user = cJSON_CreateObject();
    cJSON_AddStringToObject(user, "uid", uid);
    cJSON_AddItemToObject(root, "user", user);

    // audio 节点（必选）
    cJSON *audio = cJSON_CreateObject();
    cJSON_AddStringToObject(audio, "voice_type", voice_type);
    cJSON_AddStringToObject(audio, "encoding", encoding);
    cJSON_AddNumberToObject(audio, "speed_ratio", 1.0);  // 语速（0.1~2.0）
    cJSON_AddNumberToObject(audio, "rate", 16000);       // 采样率（默认24000）
    cJSON_AddNumberToObject(audio, "loudness_ratio", 1.0);  // 音量（0.5~2.0）
    cJSON_AddBoolToObject(audio, "enable_emotion", true);  // 开启情感
    cJSON_AddStringToObject(audio, "emotion", "gentle");    // 情感类型（gentle=温柔）
    cJSON_AddNumberToObject(audio, "emotion_scale", 4.0);   // 情感强度（1~5，默认4）
    cJSON_AddItemToObject(root, "audio", audio);

    // request 节点（必选）
    cJSON *request = cJSON_CreateObject();
    cJSON_AddStringToObject(request, "reqid", reqid);
    cJSON_AddStringToObject(request, "text", text);
    cJSON_AddStringToObject(request, "operation", "query");  // HTTP 非流式固定为 query
    cJSON_AddStringToObject(request, "extra_param", "{\"disable_markdown_filter\":true}");  // 附加参数
    cJSON_AddItemToObject(root, "request", request);

    // 生成 JSON 字符串（无格式，减少传输体积）
    char *payload = cJSON_PrintUnformatted(root);
    cJSON_Delete(root);
    if (!payload) {
        my_zlog_error("Generate JSON payload failed");
        free(uid);
        return 1;
    }
    my_zlog_debug("Request Payload: %s", payload);

    // 4. 初始化 curl 并配置 HTTP 请求
    curl_global_init(CURL_GLOBAL_DEFAULT);
    CURL *curl = curl_easy_init();
    if (!curl) {
        my_zlog_error("Initialize curl failed");
        free(payload);
        free(uid);
        return 1;
    }

    // 设置请求头（关键：Authorization 分号分隔，Content-Type 为 JSON）
    struct curl_slist *headers = NULL;
    char auth_header[256] = {0};
    snprintf(auth_header, sizeof(auth_header), "Authorization: Bearer;%s", access_token);
    headers = curl_slist_append(headers, auth_header);
    headers = curl_slist_append(headers, "Content-Type: application/json");
    headers = curl_slist_append(headers, "Accept: application/json");

    if (s_http_response == NULL) {
        s_http_response_len = 0;
    }else {
        return 1;
    }

    // curl 核心配置
    curl_easy_setopt(curl, CURLOPT_URL, endpoint);
    curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
    curl_easy_setopt(curl, CURLOPT_POST, 1L);  // POST 方法
    curl_easy_setopt(curl, CURLOPT_POSTFIELDS, payload);  // 请求体
    curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, strlen(payload));
    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, http_write_callback);  // 接收响应回调
    curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);  // 开发环境禁用 SSL 证书校验（生产环境建议启用）
    curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
    curl_easy_setopt(curl, CURLOPT_TIMEOUT, 15L);  // 超时时间 15 秒（避免网络慢导致超时）
    curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 10L);  // 连接超时 10 秒

    // 5. 执行 HTTP 请求
    my_zlog_debug("Sending request to %s...", endpoint);
    CURLcode res = curl_easy_perform(curl);
    if (res != CURLE_OK) {
        my_zlog_error("curl_easy_perform failed: %s", curl_easy_strerror(res));
        free(uid);
        free(payload);
        curl_slist_free_all(headers);
        curl_easy_cleanup(curl);
        curl_global_cleanup();
        return 1;
    }

    // 6. 解析 HTTP 响应（JSON 格式）
    my_zlog_debug("Response Length: %zu bytes", s_http_response_len);
    if (s_http_response_len == 0) {
        my_zlog_error("Empty response from server");
        free(uid);
        free(payload);
        curl_slist_free_all(headers);
        curl_easy_cleanup(curl);
        curl_global_cleanup();
        return 1;
    }

    // 解析 JSON 响应
    cJSON *response_json = cJSON_Parse(s_http_response);
    if (!response_json) {
        my_zlog_error("Parse response JSON failed: %s", cJSON_GetErrorPtr());
        free(uid);
        free(payload);
        free(s_http_response);
        curl_slist_free_all(headers);
        curl_easy_cleanup(curl);
        curl_global_cleanup();
        return 1;
    }

    // // 打印完整响应（便于调试，可根据需要注释）
    // char *response_str = cJSON_Print(response_json);
    // printf("Full Response JSON (abbreviated):\n%s\n", response_str);
    // free(response_str);

    // 提取响应状态（火山引擎该接口成功码：3000 + message=Success）
    cJSON *code = cJSON_GetObjectItem(response_json, "code");
    cJSON *message = cJSON_GetObjectItem(response_json, "message");
    if (!code || code->valueint != 3000 || !message || strcmp(message->valuestring, "Success") != 0) {
        my_zlog_error("Request failed! Code: %d, Message: %s", 
                code ? code->valueint : -1, 
                message ? message->valuestring : "No message");
        cJSON_Delete(response_json);
        free(uid);
        free(payload);
        free(s_http_response);
        curl_slist_free_all(headers);
        curl_easy_cleanup(curl);
        curl_global_cleanup();
        return 1;
    }
    my_zlog_debug("Request succeeded! Code: %d, Message: %s", code->valueint, message->valuestring);

    // 关键：直接提取 data 字段的 Base64 音频字符串（接口实际返回格式）
    cJSON *audio_base64 = cJSON_GetObjectItem(response_json, "data");
    if (!audio_base64 || !audio_base64->valuestring || strlen(audio_base64->valuestring) == 0) {
        my_zlog_error("Response missing audio data (data field is empty)");
        cJSON_Delete(response_json);
        free(uid);
        free(payload);
        free(s_http_response);
        curl_slist_free_all(headers);
        curl_easy_cleanup(curl);
        curl_global_cleanup();
        return 1;
    }
    my_zlog_debug("Audio Base64 Length: %zu bytes", strlen(audio_base64->valuestring));

    // 7. Base64 解码音频数据
    size_t audio_len = 0;
    unsigned char *audio_data = base64_decode(audio_base64->valuestring, &audio_len);
    if (!audio_data || audio_len == 0) {
        my_zlog_error("Base64 decode audio failed");
        cJSON_Delete(response_json);
        free(uid);
        free(payload);
        free(s_http_response);
        curl_slist_free_all(headers);
        curl_easy_cleanup(curl);
        curl_global_cleanup();
        return 1;
    }
    my_zlog_debug("Decoded Audio Length: %zu bytes", audio_len);

    if(save_audio_file(audio_data, audio_len, TTS_ADUINO_PTAH) != 0) {//保存文件
        my_zlog_error("save_audio_file fail");
    }

    // 9. 清理资源（避免内存泄漏）
    cJSON_Delete(response_json);
    free(uid);
    free(audio_data);
    free(payload);
    free(s_http_response);
    curl_slist_free_all(headers);
    curl_easy_cleanup(curl);
    curl_global_cleanup();

    // 初始化响应缓冲
    s_http_response = NULL;
    s_http_response_len = 0;

    return 0;
}


/*
*功能: 设置播放标识
*/
void set_audio_tts_index(bool index){
    s_audio_tts_index=index;
}

/*
*功能: 发送mqtt
*/
int mqtt_audio_tts_send(int status){

     // 创建根对象
    cJSON* root = cJSON_CreateObject();
    if (root == NULL) {
        return 1;
    }
    
    // 创建body对象
    cJSON* body = cJSON_CreateObject();
    if (body == NULL) {
        cJSON_Delete(root);
        return 1;
    }

    cJSON *head = cJSON_CreateObject();
    if (head == NULL) {
        cJSON_Delete(root);
        return 1;
    }
    
    // 将body添加到root
    cJSON_AddItemToObject(root, "body", body);
    
    // 添加type和status字段到body
    cJSON_AddStringToObject(body, "type", "tts_audio");
    cJSON_AddNumberToObject(body, "status", status);

    cJSON_AddNumberToObject(head, "message_type",3020);

   cJSON_AddItemToObject(root, "body", body);
   cJSON_AddItemToObject(root, "head",head);
    
    // 生成JSON字符串
    char* json_str = cJSON_PrintUnformatted(root);
    my_zlog_debug("%s",json_str);
   
    mqtt_publish_to_all(mqtt_topic_pure_number(), json_str, 0);
    free(json_str);
    cJSON_Delete(root);

    return 0;
    
}

int mqtt_audio_tts(cJSON *body){

    // 解析type字段
    cJSON* type = cJSON_GetObjectItem(body, "type");
    if(type == NULL || strcmp(type->valuestring, "tts_audio") != 0){
        my_zlog_error("type is tts_audio error");
        return 1;
    }
    
    // 解析date字段
    cJSON* date = cJSON_GetObjectItem(body, "date");
    if(date!=NULL){
        get_audio_text_tts(date->valuestring,0);
        my_zlog_debug("text:%s",date->valuestring);
    }else {
        return 1;
    }
    
    // 解析status字段
    cJSON* status = cJSON_GetObjectItem(body, "status");
    if(mqtt_audio_tts_send(status->valueint)==0){
        set_audio_tts_index(status->valueint);
    }else{
        set_audio_tts_index(0);
        my_zlog_error("statis error");
        return 1;
    }

    cJSON* volume = cJSON_GetObjectItem(body, "volume");
    s_volume = volume->valuedouble;
    return 0;
}

/*
*功能，tts播放
*/
void video_tts_play() {
    if(s_audio_tts_index == 1) {
        if(audio_tts(get_audio_text_tts(NULL, 1))!=0){
            my_zlog_error("audio_tts fail");
            s_audio_tts_index = 0;
            return;
        }
        
        pid_t pid = fork();
        if (pid == 0) {
            // 子进程：创建新的会话组，脱离父进程组
            setsid(); // 关键！创建新的会话组
            
            char command[256];
            snprintf(command, sizeof(command), 
                     "ffmpeg -i " TTS_ADUINO_PTAH " -af \"volume=%.1f\" -f alsa default 2>/dev/null", 
                     s_volume);
            
            // 重定向标准输入输出，避免占用终端
            if (freopen("/dev/null", "r", stdin) == NULL) {
                my_zlog_error("重定向stdin失败: %s", strerror(errno));
                // 可以选择退出或继续
            }
            
            if (freopen("/dev/null", "w", stdout) == NULL) {
                my_zlog_error("重定向stdout失败: %s", strerror(errno));
            }
            
            if (freopen("/dev/null", "w", stderr) == NULL) {
                my_zlog_error("重定向stderr失败: %s", strerror(errno));
            }
            
            int res = system(command);
            _exit(res); // 使用_exit避免清理父进程资源
        } 
        else if (pid > 0) {
            // 父进程：非阻塞等待，避免僵尸进程
            int status;
            waitpid(pid, &status, WNOHANG); // 不阻塞的等待
            
            my_zlog_debug("启动独立播放进程 PID: %d", pid);
            s_audio_tts_index = 0;
        } 
        else {
            my_zlog_error("fork()失败");
            s_audio_tts_index = 0;
        }
    }
}


// void video_tts_play(){
//     if(s_audio_tts_index == 1) {
//         audio_tts(get_audio_text_tts(NULL,1));

//         char command[256];
//         snprintf(command, sizeof(command), 
//                  "ffmpeg -i " TTS_ADUINO_PTAH " -af \"volume=%.1f\" -f alsa default", 
//                  s_volume);
        
//         int res = system(command); 
//         if(res == 0) 
//             my_zlog_info("play success, volume: %.1f", s_volume);
//         else  
//             my_zlog_error("system play fail, volume: %.1f", s_volume);

//         s_audio_tts_index == 0;
//     }
// }
 