#include "appdbusobject.h"
#include "session.h"
#include "llmutils.h"
#include "private/welcomedialog.h"
#include "dbwrapper.h"

#include <QtDBus>

AppDbusObject::AppDbusObject(const QString &appId)
    : QObject(nullptr)
{
    m_chatSession = new Session(appId);
    connect(m_chatSession, &Session::error, this, &AppDbusObject::error, Qt::QueuedConnection);
    connect(m_chatSession, &Session::chatTextReceived, this, &AppDbusObject::chatTextReceived, Qt::QueuedConnection);
    connect(m_chatSession, &Session::llmAccountLstChanged, this, [this](const QString & currentAccountId, const QString & accountLst) {
        emit llmAccountLstChanged(currentAccountId, queryLLMAccountList());
    }, Qt::QueuedConnection);
}

AppDbusObject::~AppDbusObject()
{
    m_chatSession->deleteLater();
    m_chatSession = nullptr;
}

void AppDbusObject::cancelRequestTask(const QString &id)
{
    if (!checkAgreement())
        return;

    m_chatSession->cancelRequestTask(id);
}

void AppDbusObject::updateLLMAccount()
{
    if (!checkAgreement())
        return;

    m_chatSession->updateLLMAccount();
}

void AppDbusObject::executionAborted()
{
    if (!checkAgreement())
        return;

    emit m_chatSession->executionAborted();
}

QStringList AppDbusObject::requestChatText(const QString &llmId, const QString &conversation, qreal temperature, bool stream)
{
    if (!checkAgreement())
        return QStringList();;

    uint pid = QDBusConnection::sessionBus().interface()->servicePid(message().service());
    if (m_chatSession->appId() != LLMUtils::queryAppId(pid)) {
        qWarning() << LLMUtils::queryAppId(pid) << " no permission to access!";
        sendErrorReply(QDBusError::AccessDenied, "no permission to access!");
        return QStringList();
    }
    QVariantHash params = {
        {PARAM_STREAM, QVariant(stream)},
        {PARAM_TEMPERATURE, QVariant(temperature)}
    };
    const QPair<AIServer::ErrorType, QStringList> &chatText = m_chatSession->requestChatText(llmId, conversation, params);
    if (chatText.first != AIServer::NoError) {
        sendErrorReply(QDBusError::NoServer, chatText.second.value(1));
        return QStringList();
    }

    return chatText.second;
}

bool AppDbusObject::setCurrentLLMAccountId(const QString &id)
{
    if (!checkAgreement())
        return false;

    return m_chatSession->setCurrentLLMAccountId(id);
}

QString AppDbusObject::currentLLMAccountId()
{
    if (!checkAgreement())
        return QString();

    return m_chatSession->currentLLMAccountId();
}

QString AppDbusObject::queryLLMAccountList()
{
    if (!checkAgreement())
        return QString();

    QList<LLMChatModel> excludes;
    excludes << LLMChatModel::LOCAL_TEXT2IMAGE;
    return m_chatSession->queryLLMAccountList(excludes);
}

void AppDbusObject::launchLLMUiPage(bool showAddllmPage)
{
    emit launchUI(showAddllmPage);
}

bool AppDbusObject::checkAgreement()
{
    if (WelcomeDialog::isAgreed())
        return true;

    if (QThread::currentThread() != qApp->thread()) {
        qWarning() << "this request is not in main thread. do not show WelcomeDialog.";
        return false;
    }

    WelcomeDialog::instance(false)->exec();
    return WelcomeDialog::isAgreed();
}
