#include "yourongmodelitem.h"
#include "localmodelserver.h"
#include "dbwrapper.h"
#include "externalllm/modelhubwrapper.h"
#include "downloader.h"
#include "serverwrapper.h"

#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QtConcurrent>
#include <QResizeEvent>

#include <DFontSizeManager>
#include <DDialog>

DWIDGET_USE_NAMESPACE
using namespace uos_ai;

YouRongModelItem::YouRongModelItem(DWidget *parent)
    : DWidget(parent)
{
    initUI();
    initConnect();

    QString homePath = QStandardPaths::writableLocation(QStandardPaths::HomeLocation);
    m_installPath = homePath + "/.local/share/deepin-modelhub/models";
    m_baseUrl = "https://www.modelscope.cn/models/uniontech-yourong";
    m_modelFileList << "/modelhub/config.json"
                    << "/modelhub/LICENSE"
                    << "/modelhub/template"
                    << "/modelhub/template_dsl"
                    << "/modelhub/template_func";
}

YouRongModelItem::~YouRongModelItem()
{
}

void YouRongModelItem::initUI()
{
    m_pLabelTheme = new DLabel;
    DFontSizeManager::instance()->bind(m_pLabelTheme, DFontSizeManager::T6, QFont::Medium);
    m_pLabelSummary = new DLabel;
    DFontSizeManager::instance()->bind(m_pLabelSummary, DFontSizeManager::T8, QFont::Normal);
    m_pLabelSummary->setElideMode(Qt::ElideRight);

    QVBoxLayout *textLayout = new QVBoxLayout;
    textLayout->setContentsMargins(0, 0, 0, 0);
    textLayout->setSpacing(2);
    textLayout->addWidget(m_pLabelTheme, 0, Qt::AlignLeft);
    textLayout->addWidget(m_pLabelSummary, 0, Qt::AlignLeft);

    m_pBtnInstall = new DSuggestButton(tr("Install"));
    m_pBtnInstall->setFixedHeight(30);
    m_pBtnInstall->setMinimumWidth(70);

    m_pBtnUninstall = new DPushButton(tr("Uninstall"));
    m_pBtnUninstall->setFixedHeight(30);
    m_pBtnUninstall->setMinimumWidth(70);
    m_pBtnUninstall->hide();

    m_pBtnStop = new DPushButton(tr("Stop"));
    m_pBtnStop->setFixedHeight(30);
    m_pBtnStop->setMinimumWidth(70);
    m_pBtnStop->hide();

    QHBoxLayout *mainLayout = new QHBoxLayout(this);
    mainLayout->setContentsMargins(10, 10, 10, 10);
    mainLayout->addLayout(textLayout);
    mainLayout->addStretch();
    mainLayout->addWidget(m_pBtnInstall, 0, Qt::AlignVCenter);
    mainLayout->addWidget(m_pBtnUninstall, 0, Qt::AlignVCenter);
    mainLayout->addWidget(m_pBtnStop, 0, Qt::AlignVCenter);

    setLayout(mainLayout);
}

void YouRongModelItem::initConnect()
{
    connect(m_pBtnInstall, &DSuggestButton::clicked, this, &YouRongModelItem::onInstall);
    connect(m_pBtnUninstall, &DSuggestButton::clicked, this, &YouRongModelItem::onUninstall);
    connect(m_pBtnStop, &DSuggestButton::clicked, this, &YouRongModelItem::stopDownload);
    connect(&LocalModelServer::getInstance(), &LocalModelServer::modelPluginsStatusChanged, this, &YouRongModelItem::checkInstallStatus);
}

void YouRongModelItem::setText(const QString &theme, const QString &summary)
{
    m_pLabelTheme->setText(theme);
    m_pLabelSummary->setText(summary);
    m_pLabelSummary->setToolTip(summary);
}

void YouRongModelItem::setAppName(const QString &appName)
{
    m_appName = appName;
}

void YouRongModelItem::onInstall()
{
    if (m_appName.isEmpty())
        return;
    m_pBtnInstall->setText(tr("Installing"));
    m_pBtnInstall->setEnabled(false);
    m_pBtnStop->show();

    QDir destinationDir(m_installPath + "/." + m_appName);

    if (destinationDir.mkpath("gguf")) {
        qInfo() << "Directory created successfully:";
    } else {
        qWarning() << "Failed to create directory:" ;
        return;
    }

    destinationDir.cd("gguf");

    m_downloader.reset(new Downloader(destinationDir.absolutePath()));
    connect(m_downloader.data(), &Downloader::downloadFinished, this, &YouRongModelItem::onDownloadFinished);
    connect(m_downloader.data(), &Downloader::onDownloadProgress, this, &YouRongModelItem::onDownloadProgress);

    m_lastProgress = 0.0;

    if (YOURONG1_5B == m_appName)
        m_modelFileList << "/yourong_1.5B_bf16_Q4_K_M.gguf";
    else
        m_modelFileList << "/yourong_7B_bf16_Q4_K_M.gguf";

    foreach (const QString &fileUrl, m_modelFileList) {
        QString url = m_baseUrl + "/" + m_appName + "/resolve/master" + fileUrl;
        m_downloader->addDownloadTask(QUrl(url));
    }

    adjustSummaryLabelWidth();
}

void YouRongModelItem::onUninstall()
{
    if (m_appName.isEmpty())
        return;
//    m_pBtnUninstall->setText(tr("Uninstalling"));

    DDialog dlg(this);
    dlg.setIcon(QIcon(":/assets/images/warning.svg"));
    dlg.setMaximumWidth(380);
    dlg.setTitle(tr("Are you sure you want to delete this model?"));
    dlg.addButton(tr("Cancel", "button"), false, DDialog::ButtonNormal);
    dlg.addButton(tr("Confirm", "button"), true, DDialog::ButtonRecommend);

    if (DDialog::Accepted == dlg.exec()) {
        QString modelName = m_installPath;
        if (YOURONG1_5B == m_appName)
            modelName += "/YouRong-1.5B";
        else
            modelName += "/YouRong-7B";

        QDir installFile(modelName);

        if (installFile.exists()) {
            if (installFile.removeRecursively())
                qInfo() << "Directory removed successfully.";
            else
                qWarning() << "Failed to remove directory.";
        }
        checkInstallStatus();
    }
}

void YouRongModelItem::checkInstallStatus()
{
    bool lastStatus = m_isInstall;
    m_isInstall = ModelhubWrapper::isModelInstalled(YOURONG1_5B == m_appName ? "YouRong-1.5B" : "YouRong-7B");

    if (lastStatus != m_isInstall)
        ServerWrapper::instance()->updateLLMAccount();

    //判断模型是否在用户路径
    if (m_isInstall) {
        QString modelPath = m_installPath + "/" + (YOURONG1_5B == m_appName ? "YouRong-1.5B" : "YouRong-7B");
        QDir modelDir(modelPath);
        m_pBtnUninstall->setEnabled(modelDir.exists());
    }
    changeInstallStatus();
}

void YouRongModelItem::changeInstallStatus()
{
    if (m_appName.isEmpty()) return;

    //本地模型安装信号
//    LocalModelServer::getInstance().localModelStatusChanged(m_appName, m_isInstall);

    if (m_isInstall) {
        m_pBtnInstall->hide();
        m_pBtnUninstall->show();
        m_pBtnStop->hide();
    } else {
        m_pBtnUninstall->hide();
        m_pBtnInstall->show();
        m_pBtnStop->hide();
        m_pBtnInstall->setText(tr("Install"));
        m_pBtnInstall->setEnabled(true);
        if (ModelhubWrapper::isModelhubInstalled()) {
            m_pBtnInstall->setToolTip("");
        } else {
            m_pBtnInstall->setEnabled(false);
            m_pBtnInstall->setToolTip(tr("Please install the \"Embedding Plugins\" first before installing this model."));
        }
    }

    if (m_downloader && !m_downloader->isFinished()) {
            m_pBtnInstall->setEnabled(false);
            m_pBtnStop->show();
        }

    adjustSummaryLabelWidth();
}

bool YouRongModelItem::getInstallStatus()
{
    return m_isInstall;
}

void YouRongModelItem::resizeEvent(QResizeEvent *event)
{
    DWidget::resizeEvent(event);
    adjustSummaryLabelWidth();
}

void YouRongModelItem::adjustSummaryLabelWidth()
{
    m_pBtnInstall->adjustSize();
    m_pBtnUninstall->adjustSize();

    int maxWidth = this->size().width() - 40;
    if (m_isInstall)
        maxWidth -= m_pBtnUninstall->width();
    else
        maxWidth -= m_pBtnInstall->width();

    if (m_pBtnStop->isVisible())
        maxWidth -= m_pBtnStop->width();

    m_pLabelSummary->setMaximumWidth(maxWidth < 0 ? 0 : maxWidth);
}

void YouRongModelItem::stopDownload()
{
    if (m_downloader && !m_downloader->isFinished() && !m_isInstall) {
        QString modelName = m_installPath + "/." + m_appName;

        QDir installFile(modelName);

        if (installFile.exists()) {
            if (installFile.removeRecursively())
                qDebug() << "Directory removed successfully.";
            else
                qWarning() << "Failed to remove directory.";
        }
        m_downloader->cancelDownloads();
        checkInstallStatus();
    }
}

void YouRongModelItem::onDownloadFinished()
{
    QString originalFolderPath = m_installPath + "/." + m_appName;

    QString targetFolderPath = m_installPath;

    if (YOURONG1_5B == m_appName)
        targetFolderPath += "/YouRong-1.5B";
    else
        targetFolderPath += "/YouRong-7B";

    QDir dir(originalFolderPath);

    if (dir.exists()) {
        if (dir.rename(originalFolderPath, targetFolderPath)) {
            qDebug() << "Folder renamed successfully.";
        } else {
            qWarning() << "Folder renaming failed.";
        }
    }
    checkInstallStatus();
}

void YouRongModelItem::onDownloadProgress(qint64 bytesReceived, qint64 bytesTotal)
{
    if (m_downloader && !m_downloader->isFinished()) {
        if (bytesTotal == 0)
            return;

        double progress = static_cast<double>(bytesReceived) / static_cast<double>(bytesTotal) * 100.0;
        progress = round(progress * 100) / 100;
        if (progress >= m_lastProgress) {
            m_pBtnInstall->setText(tr("Installing ") + QString::number(progress, 'f', 1) + "%");
            m_pBtnInstall->adjustSize();
            m_lastProgress = progress;
            adjustSummaryLabelWidth();
        }
    }
}
