#include "voicechatreader.h"
#include "global/voiceusingmanager.h"
#include <cmark.h>
#include <QJsonObject>
#include <QJsonDocument>
#include <QMetaObject>

/**
 * @brief 文本合成语音回调函数
 * @param 返回结果
 * @param 用户数据
 */
static void synthesisResultCallback(SpeechSynthesisResult *result, void *user_data)
{
    VoiceChatReader *chatReader = static_cast<VoiceChatReader*>(user_data);
    if (chatReader == nullptr) {
        KyInfo() << "Invalid callback user data pointer.";
        return;
    }
    if (chatReader->m_soundFlag) {
        return;
    }

    SpeechResultReason reason = speech_synthesis_result_get_reason(result);
    int errorCode = speech_synthesis_result_get_error_code(result);

    if(errorCode != 0 && errorCode != -1) {
        KyInfo() << "当前错误码为" << errorCode;
        // 错误时必须停止当前朗读（否则队列中已缓存音频会继续播放）
        // 回调线程不一定是对象所属线程，使用异步投递避免线程问题。
        QMetaObject::invokeMethod(chatReader, [chatReader, errorCode]() {
            if (chatReader->m_sdl2Player) {
                chatReader->m_sdl2Player->clearQueue();
                chatReader->m_sdl2Player->stop();
            }
            chatReader->m_waitingReadingList.clear();
            chatReader->m_isReaderSpeechSynthesizing = false;
            chatReader->isNeedRead = false;

            chatReader->parseAndSendErrorMsg(errorCode);
            Q_EMIT chatReader->sigReadEnd(0);
            Q_EMIT chatReader->sigResetPreIndex();
        }, Qt::QueuedConnection);
        return;
    }
    //获取回调函数中的有效音频数据进行合成
    {uint32_t dataLength = 0;
    const uint8_t *pcmData = speech_synthesis_result_get_data(result, &dataLength);
    KyInfo() << "回调 reason: SPEECH_SYNTHESIZING, 获取到的数据指针:" << pcmData << "长度:" << dataLength;
    if (pcmData && dataLength > 0) {
        // 初始化 SDL 播放器（如果尚未初始化）
        if (!chatReader->m_sdl2Player->isInitialized()) {
            // 从结果中获取音频参数
            int sampleRate = speech_synthesis_result_get_audio_rate(result);
            int channels = speech_synthesis_result_get_audio_channel(result);

            bool initOk = chatReader->m_sdl2Player->init(sampleRate, channels, AUDIO_S16LSB);
            if (!initOk) {
                // 首次失败可能是音频系统冷启动，短暂延迟后重试一次
                QThread::msleep(300);
                initOk = chatReader->m_sdl2Player->init(sampleRate, channels, AUDIO_S16LSB);
            }
            if (initOk) {
                KyInfo() << "SDL 音频播放器初始化成功。采样率:" << sampleRate << "声道数:" << channels;
            } else {
                KyInfo() << "SDL 音频播放器初始化失败！";
                chatReader->m_soundFlag = true;
                return;
            }
        }

        // 将数据入队并播放
        chatReader->m_sdl2Player->enqueueData(QByteArray(reinterpret_cast<const char*>(pcmData), dataLength));
        if (!chatReader->m_sdl2Player->isPlaying() && chatReader->isNeedRead) {
            chatReader->m_sdl2Player->play();
            KyInfo() << "SDL 开始播放音频。";
        }
    } else {
            KyInfo() << "SPEECH_SYNTHESIZING 回调，但未获取到有效音频数据。";
        }
    }
    if (reason == SPEECH_SYNTHESIS_COMPLETED) {
        KyInfo() << "本次发送的语音合成全部完成。";
        //检查是否还有其他需要待合成
        if(!chatReader->m_waitingReadingList.isEmpty()) {
           bool addFlag = chatReader->continueAddReadingText(
                       chatReader->m_waitingReadingList.first(),
                       chatReader->getCurrentReadIndex());
            if(addFlag) {
                chatReader->m_waitingReadingList.removeFirst();

                KyInfo() << "本次朗读结束后追加内容成功，已删除本次添加内容，当前待朗读内容"<< chatReader->m_waitingReadingList;
            }
            else {
                KyInfo() << "本次朗读结束后追加内容失败";
            }
        }
        else {
            chatReader->m_isReaderSpeechSynthesizing = false; //合成完成后将标志位设置为false,表示未进行合成操作
        }
    }
    else if (reason == SPEECH_SYNTHESIS_STARTED) {
        KyInfo() << "语音合成任务已启动。";
    }

    return;
}
VoiceChatReader::VoiceChatReader(QObject *parent)
    : QObject{parent}
    ,m_isReaderSpeechSynthesizing(false)
    ,m_workerThread(nullptr)
{
    m_sdl2Player = new SDL2AudioPlayerThread(this); // 初始化SDL播放器

    initConnect();
}

VoiceChatReader::~VoiceChatReader()
{
    closeReaderSession();

    m_sdl2Player->clearQueue();
    m_sdl2Player->deleteLater();
    m_sdl2Player = nullptr;
}

void VoiceChatReader::initConnect()
{
    // 连接SDL播放器的信号
    connect(m_sdl2Player, &SDL2AudioPlayerThread::playbackFinished, this, [=]() {
        KyInfo() << "SDL playback finished signal received.";
        // 在这里处理播放结束后的逻辑
        emit sigReadEnd(0);
        m_sdl2Player->stop();
    });

    connect(m_sdl2Player, &SDL2AudioPlayerThread::underflow, this, []() {
        KyInfo() << "Audio underflow detected. Consider enqueuing more data.";
    });

    return;
}

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

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

    // 将对象移动到工作线程
    this->moveToThread(m_workerThread);
    
    // 注意：SDL2AudioPlayerThread 本身就是一个线程，不需要移动到其他线程

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

bool VoiceChatReader::initReaderSession()
{
    if(this->m_readerSession != nullptr)
        return true;
    QString error;

    KyInfo() << "*** start initSession speech_synthesizer_create_session()";

    SpeechSynthesizerSession *m_session = speech_synthesizer_create_session();
    if(m_session == nullptr) {
        KyInfo() << "error : speech_synthesizer_create_session failed!";
        //TODO： 错误处理
        return false;
    }
    KyInfo() << "*** end initSession speech_synthesizer_create_session()";

    KyInfo() << "*** start initSession speech_synthesizer_init_session()";

    int ret =  speech_synthesizer_init_session(m_session);
    if(ret){
        KyInfo() << "reader init session error:" << ret;
        // 错误处理
        parseAndSendErrorMsg(ret);
        return false;
    }
    KyInfo() << "*** end initSession speech_synthesizer_init_session()";

    if(m_session) {
        this->m_readerSession = m_session;
    }else {
         return false;
    }

    speech_synthesizer_result_set_callback(m_readerSession, synthesisResultCallback, this);

    return true;
}

bool VoiceChatReader::closeReaderSession()
{
    if(this->m_readerSession != nullptr){
        SpeechSynthesizerSession ** sSession = &m_readerSession;
        speech_synthesizer_destroy_session(sSession);
    }
    this->m_readerSession = nullptr;
    m_isReaderSpeechSynthesizing = false;
    isNeedRead = false;
    m_sdl2Player->clearQueue();
    m_sdl2Player->stop();
    stopReading();

    return true;
}

void VoiceChatReader::startReading()
{
    KyInfo() << "reader startReading";

    if(m_sdl2Player) {
        m_sdl2Player->play();
    }

    isNeedRead = true;

    return;
}

void VoiceChatReader::pauseReading()
{
    if(isNeedRead) {
        isNeedRead = false;
    }

    if(m_sdl2Player) {
        m_sdl2Player->pause();
    }

    return;
}

void VoiceChatReader::stopReading()
{
    if(m_sdl2Player) {
        m_sdl2Player->stop();
    }
    // 清空待朗读队列
    m_waitingReadingList.clear();
    // 设置需要朗读为false
    isNeedRead = false;
    KyInfo() << "结束语音通话朗读";

    return;
}

void VoiceChatReader::continueReading()
{
    isNeedRead = true;

    //检查播放器状态，如果播放器队列为空则返回，否则则进行播放
    if(m_sdl2Player->isQueueEmpty()) {

        return;
    }else {
        m_sdl2Player->play();
        emit sigPlayingStart();
    }
}

void VoiceChatReader::interruptReading()
{
    // 打断播放
    if(m_sdl2Player->isPlaying()) {
        m_sdl2Player->clearQueue(); //清空队列
        m_sdl2Player->stop();//停止播放
    }
    // 清空待朗读队列
    m_waitingReadingList.clear();
    // 设置需要朗读为false
    isNeedRead = false;

    return;
}

bool VoiceChatReader::getCurrentReaderStatus()
{
    bool readerStatus = m_sdl2Player->isPlaying() || m_isReaderSpeechSynthesizing;
    KyInfo() << "当前朗读模块状态为" << readerStatus << "播放器是否正在播放：" <<m_sdl2Player->isPlaying()
             << "当前是否正在进行语音合成" << m_isReaderSpeechSynthesizing;
    return readerStatus;
}

bool VoiceChatReader::sendReadingText(const QString &msg, int index)
{
    KyInfo() << "发送待朗读文本" << msg;
    if (msg.length() == 0) {
        KyInfo() << "文本为空";
        Q_EMIT sigReadEnd(index);
        Q_EMIT sigResetPreIndex();

        return false;
    }

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

    if(!initReaderSession()) {
        KyInfo() << "初始化session失败，文字发送失败，已经返回";
        Q_EMIT sigReadEnd(index);
        Q_EMIT sigResetPreIndex();

        return false;
    }
    m_soundFlag = false;

    //记录播放语音的index值，音频播放结束时使用
    m_index = index;

    // 暂停原有播放并清除原有播放队列内容
//    if(m_sdl2Player) {
//        m_sdl2Player->stop();
//    }

    // 使用pcm原始音频文件作为输出源
    auto *synthesizerConfig = audio_config_create_audio_output_from_pcm_data();
    audio_config_set_input_audio_rate(synthesizerConfig, 16000);
    speech_synthesizer_set_audio_config(m_readerSession, synthesizerConfig);

    QByteArray array = msg.toUtf8();
    const char* text = array.data();

    speech_synthesizer_synthesize_text_async(m_readerSession, text, (uint32_t)(array.length()));

    isNeedRead = true;
    m_isReaderSpeechSynthesizing = true;

    return true;
}

bool VoiceChatReader::continueAddReadingText(const QString &msg, int index)
{
    KyInfo() << "发送待追加朗读文本" << msg;
    if (msg.length() == 0) {
        KyInfo() << "文本为空";
        Q_EMIT sigReadEnd(index);
        Q_EMIT sigResetPreIndex();

        return false;
    }
    if(!initReaderSession()) {
        KyInfo() << "初始化session失败，文字发送失败，已经返回";
        Q_EMIT sigReadEnd(index);
        Q_EMIT sigResetPreIndex();

        return false;
    }

    // 使用pcm原始音频文件作为输出源
    auto *synthesizerConfig = audio_config_create_audio_output_from_pcm_data();
    audio_config_set_input_audio_rate(synthesizerConfig, 16000);
    speech_synthesizer_set_audio_config(m_readerSession, synthesizerConfig);

    QByteArray array = msg.toUtf8();
    const char* text = array.data();

    speech_synthesizer_synthesize_text_async(m_readerSession, text, (uint32_t)(array.length()));

    isNeedRead = true;
    m_isReaderSpeechSynthesizing = true;

    return true;
}

int VoiceChatReader::getCurrentReadIndex()
{
    return m_index;
}

bool VoiceChatReader::insertWaitingReadingListItem(const QString &msg)
{
    qDebug() << "当前待插入朗读文本" << msg;
    if(msg.isEmpty()) {

        return true;
    }

    m_waitingReadingList.append(msg);
    if(!m_waitingReadingList.isEmpty())   {

        // 如果正在合成，则追加到列表尾部就返回
        if(m_isReaderSpeechSynthesizing) {
            qDebug() << "当前正在合成，则等待合成完成后再执行当前内容";

            return true;
        } else {
            // 如果不是正在合成，则追加到列表并发送文本
            qDebug() << "当前不是正在合成，开始发送待朗读文本，发送完成后并删除待朗读此内容";
            // 发送本次朗读文本
            if(sendReadingText(msg,m_index)){
                m_waitingReadingList.takeFirst();
                return true;
            }
            else {
                qDebug() << "本次朗读内容发送失败";
                return false;
            }

        }

    }

    return true;
}

void VoiceChatReader::clearWaitingReadingList()
{
    m_waitingReadingList.clear();

    return;
}

void VoiceChatReader::updateCurReadIndex(const int &index)
{
    qDebug() << "当前待更新朗读索引" << index;

    m_index = index;

    return;
}

void VoiceChatReader::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 sigReceiveReaderMessage(QString::fromUtf8(QJsonDocument(msg).toJson()));

    return;
}

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

QString VoiceChatReader::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;
}
