// SPDX-FileCopyrightText: 2026 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: GPL-3.0-or-later
#include "webrichetextmanager.h"
#include "jscontent.h"
#include "db/vnoteitemoper.h"
#include "metadataparser.h"
#include "common/utils.h"
#include "handler/voice_to_text_task_manager.h"

#include <QTimer>
#include <QEventLoop>
#include <QDebug>
#include <QStandardPaths>
#include <QDir>
#include <QUrl>
#include <QUuid>


WebRichTextManager::WebRichTextManager(QObject *parent)
: QObject(parent)
{
    qInfo() << "WebRichTextManager constructor called";
    initUpdateTimer();
    initConnect();
    qInfo() << "WebRichTextManager constructor finished";
}

void WebRichTextManager::initData(VNoteItem *data, const QString reg, bool focus)
{
    qInfo() << "Initializing data for note ID:" << (data ? data->noteId : -1);
    //重置鼠标点击位置
    m_mouseClickPos = QPoint(-1, -1);
    m_setFocus = focus;
    // 若数据为空，清空页面并返回，避免后续异步回调空指针
    if (!data) {
        qWarning() << "initData called with null data, clearing JS content";
        m_noteData = nullptr;
        if (m_updateTimer) m_updateTimer->stop();
        clearJSContent();
        return;
    }
    // 保存当前数据供 onLoadFinsh 以及异步回调使用
    m_noteData = data;
    //富文本设置异步操作，解决笔记列表不实时刷新
    QTimer::singleShot(50, this, [this, reg] {
        // 使用成员 m_noteData 避免捕获过期指针
        if (!m_noteData) {
            qWarning() << "Deferred setData skipped due to null m_noteData";
            return;
        }
        setData(m_noteData, reg);
    });
    qInfo() << "Data initialization finished";
}

void WebRichTextManager::initConnect()
{
    qInfo() << "Initializing connections";
    connect(JsContent::instance(), &JsContent::textChange, this, [=](){
        m_textChange = true;
        m_textChangeNoteId = m_noteData ? m_noteData->noteId : -1;
        ++m_textChangeSerial;
        emit noteTextChanged();
    });

    connect(JsContent::instance(), &JsContent::scrollTopChange, this, [=](bool isTop){
        emit scrollChange(isTop);
    });
    connect(JsContent::instance(), &JsContent::setDataFinsh, this, &WebRichTextManager::onSetDataFinsh);
    qInfo() << "Connections initialized";
}

void WebRichTextManager::setData(VNoteItem *data, const QString reg)
{
    qDebug() << "Setting rich text data";
    if (!data) {
        qWarning() << "setData called with null data, skip";
        return;
    }
    m_noteData = data;
    m_updateTimer->stop();
    //设置富文本内容
    if (data->htmlCode.isEmpty()) {
        qDebug() << "Initializing with metadata";
        emit JsContent::instance()->callJsInitData(data->metaDataRef().toString());
    } else {
        qDebug() << "Setting HTML content";
        emit JsContent::instance()->callJsSetHtml(data->htmlCode);
    }
    m_updateTimer->start();
    emit updateSearch();

    // 检查该笔记是否有转换任务，恢复相应状态
    int noteId = data->noteId;
    QTimer::singleShot(500, this, [noteId]() {
        auto tasks = VoiceToTextTaskManager::instance()->getTasksForNote(noteId);
        for (const auto &task : tasks) {
            if (task.status == VoiceToTextTask::Converting) {
                // 任务还在进行中，显示转换中状态（使用 voiceId 定位）
                qInfo() << "Restoring voice-to-text converting status for voiceId:" << task.voiceId;
                emit JsContent::instance()->callJsSetVoiceTextByPath(
                    task.voiceId, QString(), JsContent::AsrFlag::Start);
            } else if (task.status == VoiceToTextTask::Completed && !task.resultText.isEmpty()) {
                // 任务已完成且有结果，确保结果显示
                qInfo() << "Task completed, ensuring result is displayed for voiceId:" << task.voiceId;
                emit JsContent::instance()->callJsSetVoiceTextByPath(
                    task.voiceId, task.resultText, JsContent::AsrFlag::End);
                // 移除已处理的任务
                VoiceToTextTaskManager::instance()->removeTask(task.voiceId);
            } else if (task.status == VoiceToTextTask::Failed) {
                // 任务失败，移除转换中状态
                qInfo() << "Task failed, removing converting status for voiceId:" << task.voiceId;
                emit JsContent::instance()->callJsSetVoiceTextByPath(
                    task.voiceId, QString(), JsContent::AsrFlag::End);
                // 移除已处理的任务
                VoiceToTextTaskManager::instance()->removeTask(task.voiceId);
            }
        }
    });

    qInfo() << "Rich text data setting finished";
}

void WebRichTextManager::initUpdateTimer()
{
    qInfo() << "Initializing update timer";
    m_updateTimer = new QTimer(this);
    m_updateTimer->setInterval(1000);
    connect(m_updateTimer, &QTimer::timeout, this, &WebRichTextManager::updateNote);
    qInfo() << "Update timer initialized";
}

void WebRichTextManager::updateNote()
{
    // qInfo() << "Updating note, text change flag:" << m_textChange;
    if (m_textChange) {
        if (m_updateInProgress) {
            return;
        }
        m_updateInProgress = true;
        m_updateRequestNoteId = m_textChangeNoteId;
        m_updateRequestSerial = m_textChangeSerial;
        emit needUpdateNote(m_updateRequestNoteId);
    }
    // qInfo() << "Note update finished";
}

bool WebRichTextManager::hasPendingTextChange() const
{
    return m_textChange;
}

int WebRichTextManager::pendingTextChangeNoteId() const
{
    return m_textChangeNoteId;
}

int WebRichTextManager::currentNoteId() const
{
    return m_noteData ? m_noteData->noteId : -1;
}

void WebRichTextManager::requestUpdateNoteNow()
{
    updateNote();
}

void WebRichTextManager::onUpdateNoteWithResult(VNoteItem *data, const QString &result)
{
    qDebug() << "Updating note with result";
    if (!data) {
        qWarning() << "onUpdateNoteWithResult called with null data, skip";
        m_updateInProgress = false;
        m_updateRequestNoteId = -1;
        m_updateRequestSerial = 0;
        emit finishedUpdateNote();
        return;
    }
    data->htmlCode = result;
    VNoteItemOper noteOps(data);
    const bool updateOk = noteOps.updateNote();
    if (!updateOk) {
        qWarning() << "Failed to save note";
    } else {
        qDebug() << "Note saved successfully";
    }
    if (updateOk && data->noteId == m_textChangeNoteId && m_updateRequestSerial == m_textChangeSerial) {
        m_textChange = false;
        m_textChangeNoteId = -1;
    }
    m_updateInProgress = false;
    m_updateRequestNoteId = -1;
    m_updateRequestSerial = 0;
    emit finishedUpdateNote();
    qInfo() << "Note update with result finished";
}

void WebRichTextManager::insertVoiceItem(const QString &voicePath, qint64 voiceSize)
{
    qDebug() << "Inserting voice item, path:" << voicePath << "size:" << voiceSize;
    VNVoiceBlock data;
    data.ptrVoice->voiceSize = voiceSize;
    // 存储相对路径：AppData/voicenote/ -> voicenote/...
    data.ptrVoice->voicePath = Utils::makeVoiceRelative(voicePath);
    data.ptrVoice->createTime = QDateTime::currentDateTime();
    data.ptrVoice->voiceTitle = data.ptrVoice->createTime.toString("yyyyMMdd hh.mm.ss");
    // 为新录音生成唯一标识（UUID）
    data.ptrVoice->voiceId = QUuid::createUuid().toString(QUuid::WithoutBraces);

    MetaDataParser parse;
    QVariant value;
    parse.makeMetaData(&data, value);

    emit JsContent::instance()->callJsInsertVoice(value.toString());
    qDebug() << "Voice item inserted successfully, voiceId:" << data.ptrVoice->voiceId;
}

/**
 * @brief onLoadFinsh
 * 与web端通信建立完成
 */
void WebRichTextManager::onLoadFinsh()
{
    qDebug() << "Web communication established";
    //再次设置笔记内容
    if (m_noteData && !m_loadFinshSign) {
        if (m_noteData->htmlCode.isEmpty()) {
            qDebug() << "Initializing with metadata after load";
            emit JsContent::instance()->callJsInitData(m_noteData->metaDataRef().toString());
        } else {
            qDebug() << "Setting HTML content after load";
            emit JsContent::instance()->callJsSetHtml(m_noteData->htmlCode);
        }
    }
    m_loadFinshSign = true;
    qInfo() << "Web communication establishment handling finished";
}

void WebRichTextManager::clearJSContent()
{
    qDebug() << "Clearing JS content";
    emit JsContent::instance()->callJsSetHtml("");

    // 开启100ms事件循环，保证js页面内容被刷新
    QEventLoop eveLoop;
    QTimer::singleShot(100, &eveLoop, SLOT(quit()));
    eveLoop.exec();
    qDebug() << "JS content cleared";
}

void WebRichTextManager::onSetDataFinsh()
{
    qInfo() << "Set data finished";
    if (!m_setFocus) {
        return;
    }

    m_setFocus = false;
    emit JsContent::instance()->callJsFocusEditor();
}
