#include "voicechatspeech.h"
#include <cmark.h>
#include "global/voiceusingmanager.h"

static QAudioInput* g_audioVolumeInput = nullptr;
static QIODevice* g_audioIODevice = nullptr;
static int g_currentMicVolume = 0; // 实时麦克风音量(0-100)

/**
 * @brief runtimeSpeechCallback
 *          语音合成返回回调函数，数据流式返回
 * @param result
 * @param usr_data
 */
static void finishedCallback(SpeechRecognitionResult *result, void *user_data)
{
    if(user_data == nullptr) {
            KyInfo() << "Invalid callback user data pointer.";
      }
      int errorCode = speech_recognition_result_get_error_code(result);
      KyInfo() << "ddddddddddd errorCode :" << errorCode;
      const char *result_text = speech_recognition_result_get_text(result);
      KyInfo() << "ddddddddddd result_text :" << result_text;
      int speaker_id = speech_recognition_result_get_speaker_id(result);
      KyInfo() << "ddddddddddd speaker_id :" << speaker_id;
      SpeechResultReason reason = speech_recognition_result_get_reason(result);
      KyInfo() << "ddddddddddd reason :" << reason;

      VoiceChatSpeech *voiceControl = (VoiceChatSpeech *)user_data;
      //错误码处理
      if(errorCode != 0 && errorCode != -1)
      {
          //百度模型，五秒钟未收到音频会自动断开连接，导致语音通话暂停记录后无法继续使用
          KyInfo() << "voiceChat speech callback error, errorcode :" << errorCode;
          voiceControl->parseAndSendErrorMsg(errorCode);
          return;
      }


      //发送合成消息显示到前端
      QJsonObject msg;
      msg["msgType"] = "recvChatMsg";
      QJsonObject msgBody;
      msgBody["isEnd"] =  false;
      msgBody["errorCode"] = errorCode;

      //判断识别状态，未修正语句也显示，未修正的语句在最终进行替换
      if(reason == SPEECH_RECOGNIZED){
          msgBody["recvMsg"] = result_text;
          msgBody["recognized"] = true;
      }
      else if(reason == SPEECH_RECOGNIZING) {
          msgBody["recvMsg"] = result_text;
          msgBody["recognized"] = false;
      }
      else {
          return;
      }

      msg["msgBody"] = msgBody;

      Q_EMIT voiceControl->sigReceiveSpeechRecognitionMessage(QString::fromUtf8(QJsonDocument(msg).toJson()));
      // 获取当前时间并格式化
      QString timeStamp = QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss.zzz");
      KyInfo() << "收到识别完成的语音文字时间：" << timeStamp;

      return;
}

/**
 * @brief calcCurrentVolume 核心：计算麦克风实时音量
 */
static void calcCurrentVolume()
{
    if (!g_audioIODevice) return;
    // 读取麦克风PCM音频数据
    QByteArray audioData = g_audioIODevice->readAll();
    if (audioData.isEmpty() || audioData.size() % 2 != 0) {
        g_currentMicVolume = 0;
        return;
    }

    // 16bit采样数据计算音量（绝对值均值法，行业通用）
    qint64 volSum = 0;
    const short* pcmData = reinterpret_cast<const short*>(audioData.constData());
    int sampleCount = audioData.size() / 2;

    for (int i = 0; i < sampleCount; ++i) {
        volSum += qAbs(pcmData[i]);
    }
    // 归一化到0-100音量区间
    g_currentMicVolume = qMin(100, qMax(0, (int)(volSum * 100.0 / (sampleCount * 32767))));
}

/**
 * @brief initMicVolumeMonitor 初始化麦克风音量监测（只初始化一次）
 */
static void initMicVolumeMonitor()
{
    if (g_audioVolumeInput) return;

    // 配置音频格式（与麦克风/语音识别兼容的通用格式）
    QAudioFormat audioFmt;
    audioFmt.setSampleRate(16000);
    audioFmt.setChannelCount(1);
    audioFmt.setSampleSize(16);
    audioFmt.setCodec("audio/pcm");
    audioFmt.setSampleType(QAudioFormat::SignedInt);
    audioFmt.setByteOrder(QAudioFormat::LittleEndian);

    // 校验格式并初始化音频输入
    QAudioDeviceInfo inputDev = QAudioDeviceInfo::defaultInputDevice();
    if (!inputDev.isFormatSupported(audioFmt)) {
        audioFmt = inputDev.nearestFormat(audioFmt);
    }

    g_audioVolumeInput = new QAudioInput(inputDev, audioFmt);
    g_audioIODevice = g_audioVolumeInput->start();
    // 绑定数据读取信号，实时计算音量
    QObject::connect(g_audioIODevice, &QIODevice::readyRead, calcCurrentVolume);
    KyInfo() << "麦克风音量监测初始化完成 ✅";
}

/**
 * @brief releaseMicVolumeMonitor 释放音量监测资源
 */
static void releaseMicVolumeMonitor()
{
    if (g_audioVolumeInput) {
        g_audioVolumeInput->stop();
        delete g_audioVolumeInput;
        g_audioVolumeInput = nullptr;
    }
    g_audioIODevice = nullptr;
    g_currentMicVolume = 0;
}

VoiceChatSpeech::VoiceChatSpeech(QObject *parent)
    : QObject(parent)
    , m_volumeTimer(new QTimer(this))
    , m_workerThread(nullptr) 
{
    m_volumeTimer->setInterval(500);
    connect(m_volumeTimer, &QTimer::timeout, this, [=](){
        //KyInfo() << "麦克风实时音量【定时】：" << g_currentMicVolume << "%";
        Q_EMIT this->sigCurSpeechVolume(g_currentMicVolume * 5);
    });

    // connect(VoiceUsingManager::getInstance(), &VoiceUsingManager::sigInterruptUsing, this,[&](){
    //     KyInfo() << "当前正在执行打断原有语音通话录音的流程" << this;
    //     stopSpeechRecognition();
    //     closeSpeechSession();
    // });

}

VoiceChatSpeech::~VoiceChatSpeech()
{
    if(m_speechconfig != nullptr){
        AudioConfig **cConfig = &m_speechconfig;
        audio_config_destroy(cConfig);
    }

    closeSpeechSession();
    releaseMicVolumeMonitor(); 
}

bool VoiceChatSpeech::initSpeechSession()
{
    //初始化会话时，对创建成功的会话进行判断并进行指针传递，如果创建失败则返回错误码
    if(this->m_speechSession != nullptr)
        return true;

    SpeechRecognitionSession *speechSession = nullptr;
    speechSession = speech_recognizer_create_session();
    if(speechSession != nullptr)
    {
        KyInfo() << "voice speech_recognizer_create_session successful.";
    }
    else
    {
        KyInfo() << "speech_recognizer_create_session error.";
        return false;
    }

    int errorCode = speech_recognizer_init_session(speechSession);
      if(!errorCode)
      {
          KyInfo() << "speech_init_session successful";
      }
      else
      {
          KyInfo() << "speech_init_session error:" << errorCode;
          parseAndSendErrorMsg(errorCode);

          return false;
      }

      if(!errorCode)
      {
          this->m_speechSession = speechSession;
          //设置回调函数
          speech_recognizer_result_set_callback(this->m_speechSession, finishedCallback, this);
      }
      return true;
}

void VoiceChatSpeech::closeSpeechSession()
{
    if(this->m_speechSession != nullptr){
        SpeechRecognitionSession **sSession = &m_speechSession;
        speech_recognizer_destroy_session(sSession);
    }
    this->m_speechSession = nullptr;

    m_volumeTimer->stop();
    return;
}

bool VoiceChatSpeech::startSpeechRecognition()
{
    emit  VoiceUsingManager::getInstance()->sigInterruptUsing(true);// 打断所有的音频占用

    if(!initSpeechSession())
    {
        KyInfo() << "startVoiceChat InitSession error!";
        return false;
    }
    // 初始化音量监听器
    initMicVolumeMonitor();
    m_volumeTimer->start();

    //现在直接使用默认麦克风作为数据
    m_speechconfig =audio_config_create_continuous_audio_input_from_default_microphone();
    speech_recognizer_set_audio_config(m_speechSession, m_speechconfig);
    speech_recognizer_start_continuous_recognition_async(m_speechSession);

    // 延迟发送识别已开始的信号，确保识别真正启动
    // 使用 QTimer::singleShot 在识别启动后延迟发送信号
    QTimer::singleShot(200, this, [this]() {
        emit speechRecognitionStarted();
    });

    return true;
}

void VoiceChatSpeech::pauseSpeechRecognition()
{
    KyInfo() << "pause voice Chat";
    if(this->m_speechSession){
        speech_recognizer_stop_continuous_recognition_async(m_speechSession);
    }

    m_volumeTimer->stop(); 

    return;
}

void VoiceChatSpeech::continueSpeechRecognition()
{
    KyInfo() << "continue voice Chat";
    if(this->m_speechSession)
    {
        speech_recognizer_start_continuous_recognition_async(m_speechSession);
        m_volumeTimer->start(); 
    }

    return;
}

void VoiceChatSpeech::stopSpeechRecognition()
{
    speech_recognizer_stop_continuous_recognition_async(m_speechSession);
    m_volumeTimer->stop(); 
    KyInfo() << "结束持续语音识别结果";

    return;
}

void VoiceChatSpeech::parseAndSendErrorMsg(const int errorCode)
{
    QString errorMsg = "";
    QJsonObject msg;
    msg["msgType"] = "recvAnswerMsg";
    QJsonObject msgBody;
    // 检查错误信息是否等于模型未配置
    SpeechErrorCode error = static_cast<SpeechErrorCode>(errorCode);
    if (error == AISDK_MODEL_NOT_FOUND){
        errorMsg = "<span style=\"color:red\">" + tr("There is currently no available voice model available.") + "</span> \n\n" + convertMarkDownToHtml(tr("Configuration steps:\n\n 1. Go to the **System Settings &gt; AI Module Management &gt; Model Configuration** page to add a \"cloud model\", a \"local model\" or a \"optional model\".\n 2. If the model configuration is already completed, please confirm whether the model is enabled. \n\n Note: Running a local model may consume significant device resources. Please ensure your device meets the performance requirements."));
        msgBody["colorMsg"] = "black";
    }else {
        errorMsg = Globals::getErrorMsg(error);
        msgBody["colorMsg"] = "red";
        KyInfo() << "语音通话初始化错误信息："<< errorMsg;
    }

    msgBody["isEnd"] =  true;
    msgBody["sentByUser"]  = false;
    msgBody["reasonMessage"] = "";
    msgBody["modelMsg"] = "由AI助手生成";
    msgBody["recvMsg"] = errorMsg;
    msgBody["recognized"] = true;
    msgBody["errorCode"] = errorCode;

    msg["msgBody"] = msgBody;

    Q_EMIT sigReceiveSpeechRecognitionMessage(QString::fromUtf8(QJsonDocument(msg).toJson()));



    return;
}

QString VoiceChatSpeech::convertMarkDownToHtml(const QString &markDown)
{
    // 将markDown格式转换为html格式
    if(markDown.length() < 1){
        return "";
    }else{
        return markdownToHtml(markDown.toStdString());
    }
}

QString VoiceChatSpeech::markdownToHtml(const std::string &markdown)
{
    // Convert the markdown text to HTML
    const char* markdownText = markdown.c_str();
    char* html = cmark_markdown_to_html(markdownText, strlen(markdownText), CMARK_OPT_DEFAULT);

    // Handle the conversion result
    std::string htmlStr(html);
    //cmark_mem_free(html);
    QString qStr = QString::fromStdString(htmlStr);
    return qStr;
}

void VoiceChatSpeech::moveToWorkerThread(QThread *thread)
{
    if (thread == nullptr) {
        KyInfo() << "Invalid thread pointer, cannot move VoiceChatSpeech to thread.";
        return;
    }

    m_workerThread = thread;
    
    // 启动线程
    if (!m_workerThread->isRunning()) {
        m_workerThread->start();
    }

    // 将对象移动到工作线程
    this->moveToThread(m_workerThread);
    
    // 将 QTimer 也移动到同一线程
    if (m_volumeTimer) {
        m_volumeTimer->moveToThread(m_workerThread);
    }

    KyInfo() << "VoiceChatSpeech moved to worker thread:" << m_workerThread;
}
