#include "modelupdater.h"
#include <QNetworkRequest>
#include <QNetworkReply>
#include <QFile>
#include <QDir>
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonArray>
#include <QDebug>

using namespace uos_ai;

ModelUpdater::ModelUpdater(const QString &baseUrl, const QString &dirPath,
                           const QString &appName, const QString &modelName, QObject *parent)
    : QObject(parent), m_appName(appName), m_modelName(modelName), m_baseUrl(baseUrl), m_installPath(dirPath)
{
}

void ModelUpdater::check()
{
    if (m_isRequsting)
        return;

    m_isRequsting = true;
    QNetworkRequest request(QUrl(m_baseUrl + "/" + m_appName + "/resolve/master/sha256"));
    QNetworkReply *reply = m_manager.get(request);
    connect(reply, &QNetworkReply::readyRead, this, &ModelUpdater::onReadyRead);
    connect(reply, &QNetworkReply::finished, this, [this, reply]() {
        onFinished(reply);
        reply->deleteLater();
    });
}

void ModelUpdater::saveNewHash()
{
    if (m_remote.isEmpty())
        return;
    QCryptographicHash hasher(QCryptographicHash::Sha256);
    hasher.addData(m_remote);
    QByteArray hashValue = hasher.result().toHex();

    QFile file(m_installPath + "/" + m_modelName + "/gguf/.new_sha256");
    if (file.open(QIODevice::WriteOnly | QIODevice::Text)) {
        file.write(hashValue);
        file.close();
    }
}

QPair<bool, bool> ModelUpdater::compareSha()
{
    QCryptographicHash localHasher(QCryptographicHash::Sha256);
    QFile localFile(m_installPath + "/" + m_modelName + "/gguf/sha256");
    if (localFile.open(QIODevice::ReadOnly)) {
        localHasher.addData(&localFile);
        localFile.close();
    }

    QByteArray localHash = localHasher.result().toHex();

    QCryptographicHash remoteHasher(QCryptographicHash::Sha256);
    remoteHasher.addData(m_remote);
    QByteArray remoteHash = remoteHasher.result().toHex();

    bool localCmpRemote = (localHash != remoteHash);

    bool newlocalCmpRemote = false;
    if (localCmpRemote) {
        QFile newLocalFile(m_installPath + "/" + m_modelName + "/gguf/.new_sha256");
        QByteArray newLocalHash = "";
        if (newLocalFile.open(QIODevice::ReadOnly)) {
            newLocalHash = newLocalFile.readAll().trimmed();
            newLocalFile.close();
        }

        newlocalCmpRemote = (newLocalHash != remoteHash);
    }

    return QPair<bool, bool>(localCmpRemote, localCmpRemote && newlocalCmpRemote);
}

void ModelUpdater::onReadyRead()
{
    QNetworkReply *reply = qobject_cast<QNetworkReply*>(sender());
    if (reply) {
        m_remote.clear();
        m_remote.append(reply->readAll());
    }
}

void ModelUpdater::onFinished(QNetworkReply *reply)
{
    m_isRequsting = false;
    if (reply->error() == QNetworkReply::NoError) {
        emit canUpdate(compareSha());
    } else {
        qWarning() << "Update check failed:" << reply->errorString();
    }
}
