// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: GPL-3.0-or-later

#include "llminmodelhub.h"

#include "aiconversation.h"
#include "universalchatcompletion.h"
#include "universalimage.h"

#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonArray>

using namespace uos_ai;

LLMinModelHub::LLMinModelHub(QSharedPointer<ModelhubWrapper> ins, const LLMServerProxy &serverproxy)
    : LLM(serverproxy)
    , wrapper(ins)
{

}

QPair<int, QString> LLMinModelHub::verify()
{
    if (wrapper.isNull()) {
        QPair<int, QString> errorpair(AIServer::AccountInvalid, "");
        setLastError(errorpair.first);
        setLastErrorString(errorpair.second);
        return errorpair;
    }

    wrapper->ensureRunning();

    AIConversation conversion;
    conversion.addUserData("Account verification only, no need for any response.");
    UniversalChatCompletion chatCompletion(apiUrl(), m_accountProxy.account);
    connect(this, &UniversalAPI::aborted, &chatCompletion, &UniversalChatCompletion::requestAborted);

    QPair<int, QString> errorpair = chatCompletion.create(modelId(), conversion);
    setLastError(errorpair.first);
    setLastErrorString(errorpair.second);

    return errorpair;
}

QJsonObject LLMinModelHub::predict(const QString &content, const QJsonArray &functions, const QString &systemRole, qreal temperature)
{
    if (wrapper.isNull()) {
        setLastError(AIServer::AccountInvalid);
        return QJsonObject();
    }

    wrapper->ensureRunning();

    AIConversation conversion;
    conversion.addUserData(content);
    conversion.setFunctions(functions);
    conversion.filterThink();

    if (!systemRole.isEmpty())
        conversion.setSystemData(systemRole);

    UniversalChatCompletion chatCompletion(apiUrl(), m_accountProxy.account);
    connect(this, &LLMinModelHub::aborted, &chatCompletion, &UniversalChatCompletion::requestAborted);
    connect(&chatCompletion, &UniversalChatCompletion::readyReadDeltaContent, this, &LLMinModelHub::onReadyReadChatDeltaContent);

    QPair<int, QString> errorpair = chatCompletion.create(modelId(), conversion, temperature);
    setLastError(errorpair.first);
    setLastErrorString(errorpair.second);

    QJsonObject response;
    response["content"] = conversion.getLastResponse();

    QJsonObject tools = conversion.getLastTools();
    if (!tools.isEmpty()) {
        response["tools"] = tools;
    }
    return response;
}

void LLMinModelHub::onReadyReadChatDeltaContent(const QByteArray &content)
{
    if (content.isEmpty() || !stream())
        return;

    const QJsonObject &deltacontent = AIConversation::parseContentString(content);
    if (hasThinkChain()) {
        readyThinkChainContent(deltacontent);
        return;
    }

    if (deltacontent.contains("content"))
        emit readyReadChatDeltaContent(deltacontent.value("content").toString());
}

QString LLMinModelHub::modelId() const
{
    return m_accountProxy.llmName(m_accountProxy.model);
}

QString LLMinModelHub::apiUrl() const
{
    return wrapper->urlPath("");
}
