#include "common.h"
#include "audioplay.h"
#include "device_identity.h"
#include "mqtt_init.h"
#include "http_config_mqtt.h"
#include "audiotts_play.h"
#include "wifi_autoconfig.h"
#include <strings.h>
#include <unistd.h>

static int s_audio_status=7;
static char s_urlbuf[512];
static char s_keybuf[256];
static double s_audio_volume=0.8;

#define AUDIO_DRIVING_LEVEL_MAX 30

static int s_local_play_pending = 0;
static char s_local_filepath[512];

static int local_is_cn_lang(const char *lang) {
    return lang != NULL && (strcmp(lang, AUDIO_LANG_ZH) == 0 || strcmp(lang, "cn") == 0);
}

static int local_is_en_lang(const char *lang) {
    return lang != NULL &&
           (strcmp(lang, AUDIO_LANG_EN) == 0 || strcmp(lang, "en") == 0 || strcmp(lang, "EN") == 0);
}

static void local_resolve_lang(const char *language_override, char *out, size_t size) {
    if (language_override == NULL || language_override[0] == '\0' ||
        strcasecmp(language_override, "default") == 0) {
        snprintf(out, size, "%s", audio_get_language());
        return;
    }
    if (local_is_cn_lang(language_override)) {
        snprintf(out, size, "%s", AUDIO_LANG_ZH);
        return;
    }
    if (local_is_en_lang(language_override)) {
        snprintf(out, size, "%s", AUDIO_LANG_EN);
        return;
    }
    snprintf(out, size, "%s", audio_get_language());
    my_zlog_warn("2017 未知 language: %s，使用当前语言: %s", language_override, out);
}

static int local_resolve_filepath(const char *filename, const char *language_override,
                                  char *out, size_t size) {
    char lang[8];
    int use_default_lang = (language_override == NULL || language_override[0] == '\0' ||
                            strcasecmp(language_override, "default") == 0);

    local_resolve_lang(language_override, lang, sizeof(lang));

    if (local_is_cn_lang(lang)) {
        snprintf(out, size, "%s/%s", AUDIO_LOCAL_BASE, filename);
        return access(out, F_OK) == 0;
    }

    snprintf(out, size, "%s/%s/%s", AUDIO_LOCAL_BASE, lang, filename);
    if (access(out, F_OK) == 0) {
        return 1;
    }
    if (use_default_lang) {
        snprintf(out, size, "%s/%s", AUDIO_LOCAL_BASE, filename);
        return access(out, F_OK) == 0;
    }
    return 0;
}

static void local_queue_play(const char *filename, const char *language) {
    if (!local_resolve_filepath(filename, language, s_local_filepath, sizeof(s_local_filepath))) {
        my_zlog_warn("2017 本地音频不存在: %s", filename);
        return;
    }
    s_local_play_pending = 1;
    my_zlog_info("2017 已排队本地音频: %s", s_local_filepath);
}

void audioplay_local_mqtt_receive(cJSON *body) {
    if (!cJSON_IsObject(body)) {
        my_zlog_warn("2017 body 无效");
        return;
    }

    cJSON *status = cJSON_GetObjectItemCaseSensitive(body, "status");
    cJSON *level_item = cJSON_GetObjectItemCaseSensitive(body, "level");
    cJSON *language = cJSON_GetObjectItemCaseSensitive(body, "language");

    if (!cJSON_IsString(status) || status->valuestring == NULL) {
        my_zlog_warn("2017 缺少 status");
        return;
    }

    const char *lang = "default";
    if (cJSON_IsString(language) && language->valuestring != NULL) {
        lang = language->valuestring;
    }

    if (strcmp(status->valuestring, "speed") == 0) {
        local_queue_play("Speedupforoneminute.mp3", lang);
        return;
    }

    if (strcmp(status->valuestring, "drivinglevel") == 0) {
        int level = 0;
        if (cJSON_IsString(level_item) && level_item->valuestring != NULL) {
            level = atoi(level_item->valuestring);
        } else if (cJSON_IsNumber(level_item)) {
            level = level_item->valueint;
        } else {
            my_zlog_warn("2017 drivinglevel 缺少 level");
            return;
        }
        if (level < 1 || level > AUDIO_DRIVING_LEVEL_MAX) {
            my_zlog_warn("2017 drivinglevel level 无效: %d (1-%d)",
                         level, AUDIO_DRIVING_LEVEL_MAX);
            return;
        }
        char filename[48];
        snprintf(filename, sizeof(filename), "DrivingLevel%d.mp3", level);
        local_queue_play(filename, lang);
        return;
    }

    my_zlog_warn("2017 未知 status: %s", status->valuestring);
}

static double audioplay_volume_clamp(double v) {
	if (v < 0.0) {
		return 0.0;
	}
	if (v > 2.0) {
		return 2.0;
	}
	return v;
}

int audio_wheat_init();

//接收音频播放
void audioplay_mqtt_receive(cJSON *json) {
    // 解析"audioLink"字段（修正了原始JSON中的拼写错误）
    cJSON *audio_link = cJSON_GetObjectItemCaseSensitive(json, "audioLink");
    if (cJSON_IsString(audio_link) && (audio_link->valuestring != NULL)) {
        my_zlog_debug("音频链接: %s", audio_link->valuestring);
        char *url=audio_link->valuestring;
        snprintf(s_urlbuf, sizeof(s_urlbuf), "%s", url);
    } else {
        my_zlog_warn("错误：无法解析音频链接字段");
    }

    // 解析"key"字段
    cJSON *key_char = cJSON_GetObjectItemCaseSensitive(json, "key");
    if (cJSON_IsString(key_char) && (key_char->valuestring != NULL)) {
        my_zlog_debug("音频链接KEY: %s", key_char->valuestring);
        char *key=key_char->valuestring;
        snprintf(s_keybuf, sizeof(s_keybuf), "%s", key);
    } else {
        my_zlog_warn("错误：无法解析音频链接");
        s_audio_status=5;
    }

    // 解析"status"字段
    cJSON *s_audio_status_val = cJSON_GetObjectItemCaseSensitive(json, "status");
    if (cJSON_IsNumber(s_audio_status_val)) {
        my_zlog_debug("标志: %d", s_audio_status_val->valueint);
        s_audio_status=s_audio_status_val->valueint;
    } else {
        my_zlog_warn("错误：无法解析标志字段");
    }

    // 解析"volume"字段
    cJSON *volume = cJSON_GetObjectItemCaseSensitive(json, "volume");
    if (cJSON_IsNumber(volume)) {
        my_zlog_debug("声量大小: %.3f", volume->valuedouble);
        s_audio_volume = audioplay_volume_clamp(volume->valuedouble);
    } else {
        my_zlog_warn("错误：无法解析声量字段");
    }
}  

//发送音频播放是否完毕
void  audioplay_send_mqtt() {
    cJSON *root = cJSON_CreateObject();
    cJSON *body = cJSON_CreateObject();
    cJSON *head = cJSON_CreateObject();
        // 添加各个字段到 JSON 对象
    cJSON_AddStringToObject(body, "type", "audio");
    cJSON_AddStringToObject(body, "audioLink", s_urlbuf);
    cJSON_AddStringToObject(body, "key", s_keybuf);
    cJSON_AddNumberToObject(body, "status", s_audio_status);
    cJSON_AddNumberToObject(body, "volume", s_audio_volume);

    cJSON_AddNumberToObject(head, "message_type",3001);

    cJSON_AddItemToObject(root, "body", body);
    cJSON_AddItemToObject(root, "head",head);
    // 将 JSON 对象转换为字符串
    char* json_string = cJSON_PrintUnformatted(root);
    my_zlog_debug("%s",json_string);

    mqtt_publish_to_all(mqtt_topic_pure_number(), json_string, 0);
    free(json_string);
    cJSON_Delete(root);
}

//音频播放
void audioplay_cycle(){
    char command[1024];
    int ret;
    while(1){
        if(s_audio_status==0){

            char *urlmoddle=s_urlbuf;
            s_audio_volume = audioplay_volume_clamp(s_audio_volume);
            snprintf(command, sizeof(command),
            "sudo ffplay -nodisp -autoexit -loglevel quiet -af \"volume=%.3f\" \"%s\"",
            s_audio_volume,urlmoddle);

            my_zlog_debug("播放地址: %s", s_urlbuf);
            my_zlog_debug("执行播放命令: %s", command);
            ret = system(command);
            if (ret != 0) {
                my_zlog_error("播放失败");
                s_audio_status=2;
            }

            if (WIFEXITED(ret) && WEXITSTATUS(ret) == 0) {
                my_zlog_debug("播放已成功完成 : %s ", s_urlbuf);  
                s_audio_status=1;   
            } else {
                my_zlog_warn("播放失败或中断: %s ", s_urlbuf);
                s_audio_status=2;
            }
        audioplay_send_mqtt();
        }

        if (s_local_play_pending) {
            s_local_play_pending = 0;
            snprintf(command, sizeof(command),
                     "ffplay -nodisp -autoexit -loglevel quiet \"%s\"", s_local_filepath);
            my_zlog_debug("播放本地音频: %s", s_local_filepath);
            ret = system(command);
            if (WIFEXITED(ret) && WEXITSTATUS(ret) == 0) {
                my_zlog_debug("本地音频播放完成: %s", s_local_filepath);
            } else {
                my_zlog_warn("本地音频播放失败: %s", s_local_filepath);
            }
        }

        video_tts_play();

        delay_ms(100);
    
    }
}

int audio_wheat_init(){
    int adino_jude = system("pactl load-module module-alsa-sink device=hw:2,0");
    if(adino_jude  == 0 ){
        my_zlog_debug("命令执行成功！");
        return 0;
    }else {
        if(adino_jude  != 0) my_zlog_warn("喇叭命令执行失败，返回状态码: %d", adino_jude );
        return -1;
    }
}

int audio_speaker_init() {

    int adino_play_jude =system("pactl load-module module-alsa-source device=hw:2,0");
    
    if ( adino_play_jude==0 ) {
        my_zlog_debug("命令执行成功！");
        return 0;
    } else {
        if(adino_play_jude!=0) my_zlog_warn("麦命令执行失败，返回状态码: %d", adino_play_jude );
        return -1;
    }
}

int audio_init(){

    delay_s(10);
    audio_wheat_init();
    delay_s(3);
    audio_speaker_init();

    return 0;
}


#define CONFIG_FILE "/usr/share/pulseaudio/alsa-mixer/profile-sets/default.conf"

static const char *s_yundea_block =
"# 为 Yundea 1076 USB 二合一设备添加配置\n"
"[Mapping yundea-input]\n"
"device-strings = hw:%f,0\n"
"direction = input\n"
"priority = 100\n"
"channel-map = mono\n"
"\n"
"[Mapping yundea-output]\n"
"device-strings = hw:%f,0\n"
"direction = output\n"
"priority = 100\n"
"channel-map = left,right\n"
"\n"
"[Profile yundea-duplex]\n"
"input-mappings = yundea-input\n"
"output-mappings = yundea-output\n"
"priority = 200\n";

/*
*功能：加入usb声卡配置
*
*/
int audio_config_init() {

    delay_s(20);//延迟30s

    FILE *fp = fopen(CONFIG_FILE, "r");
    if (!fp) {
        perror("无法打开配置文件进行读取");
        return 1;
    }

    // 获取文件大小
    fseek(fp, 0, SEEK_END);
    long size = ftell(fp);
    fseek(fp, 0, SEEK_SET);

    char *buffer = malloc(size + 1);
    if (!buffer) {
        my_zlog_error("内存分配失败");
        fclose(fp);
        return 1;
    }

    size_t result =fread(buffer, 1, size, fp);
    if (result != size) {
    my_zlog_warn("Error: Failed to read audio data");
    }
    buffer[size] = '\0';
    fclose(fp);

    // 检查是否包含完整配置块
    if (strstr(buffer, s_yundea_block) != NULL) {
        my_zlog_debug("配置文件中已包含指定配置，跳过添加。");
        free(buffer);
        return 0;
    }

    free(buffer);

   my_zlog_info("未找到指定配置，正在追加到文件末尾...");

    // 打开文件追加配置
    fp = fopen(CONFIG_FILE, "a");
    if (!fp) {
        my_zlog_error("无法打开配置文件进行写入");
        return 1;
    }

    fprintf(fp, "\n%s", s_yundea_block);
    fclose(fp);

    my_zlog_info("配置已成功追加。");
    return 0;
}