#include "privatemodelconfigdialog.h"
#include "aisubsystem.h"
#include "util.h"

PrivateModelConfigDialog::PrivateModelConfigDialog(PrivateModel model, QWidget *parent) :
    QDialog(parent)
{
    isEdit = true;
    initLayout();
    initConnect();
    changeTheme();


    buttonAccept->setText(tr("Ok"));

    loadModelData(model);

}

PrivateModelConfigDialog::PrivateModelConfigDialog(QWidget *parent) : QDialog(parent)
{
    isEdit = false;
    initLayout();
    initConnect();
    changeTheme();
}

PrivateModelConfigDialog::~PrivateModelConfigDialog()
{

}

void PrivateModelConfigDialog::initUIData(AiCapability capability, const DeployType deployType)
{
    m_capability = capability;
    if(m_capability == AiCapability::Nlp){
        this->setWindowTitle(tr("Add-NLP Model")); //添加-语言大模型
    }else if(m_capability == AiCapability::Vision){
        this->setWindowTitle(tr("Add-Visual Model")); //添加-视觉大模型
    }else if(m_capability == AiCapability::Speech){
        this->setWindowTitle(tr("Add-Speech Model")); //添加-语音大模型
    }
}
// 编辑- 加载对应模型数据
void PrivateModelConfigDialog::loadModelData(PrivateModel model)
{
    m_model = model;
    m_capability = model.capability;
    std::vector<MultiAuthentication> modelsAuthens = model.multiAuths;

    if(m_capability == AiCapability::Nlp){
        this->setWindowTitle(tr("Edit-NLP Model")); // 编辑-语言大模型
    }else if(m_capability == AiCapability::Vision){
        this->setWindowTitle(tr("Edit-Visual Model")); //编辑-视觉大模型
    }else if(m_capability == AiCapability::Speech){
        this->setWindowTitle(tr("Edit-Speech Model")); //编辑-语音大模型
    }
    for (const auto &authen : modelsAuthens) {
        for (const auto &au : authen.authentications) {
            if (au.key == "apiKey") {
                passwordEditApi->setText(QString::fromStdString(au.value));
            }

        }
    }
    lineeditCustomName->setText(model.modelName);
    lineeditModelName->setText(model.modelVersion);
    passwordEditApi->setText(model.apiKey);
    lineeditRequestUrl->setText(model.apiUrl);
    passwordEditApi->setEchoMode(QLineEdit::Password);
    passwordEditApi->setEchoModeBtnVisible(true);

    //moveToCenter();
}

void PrivateModelConfigDialog::keyPressEvent(QKeyEvent *event)
{
    // Key_Enter是小键盘的确认键，Key_Return是大键盘的回车键
    if (event->key() == Qt::Key_Return || event->key() == Qt::Key_Enter) {
        if (buttonAccept->isEnabled()) {
            emit accept();
        }
    }
}

void PrivateModelConfigDialog::onPasswordEditChanged(KPasswordEdit *passwordEdit)
{
    if (passwordEdit->text().length() == 0) {
        passwordEdit->setEchoModeBtnVisible(true);
    }
//    updateButtonState();

}

void PrivateModelConfigDialog::changeTheme()
{

}

void PrivateModelConfigDialog::initLayout()
{
    setFixedSize(420, 276);

    labelCustomName = new kdk::KLabel;
    labelCustomName->setAccessibleName("kylin-ai-subsystem-modelconfig_QLabel_labelAccountName");
    labelCustomName->setText(tr("CustomName"));
    labelCustomName->setFixedWidth(80);
    labelModelName = new kdk::KLabel;
    labelModelName->setText(tr("ModelName"));
    labelModelName->setAccessibleName("kylin-ai-subsystem-modelconfig_QLabel_labelModelName");
    labelModelName->setFixedWidth(80);
    labelApiKey = new QLabel("APIKey");
    labelApiKey->setAccessibleName("kylin-ai-subsystem-modelconfig_QLabel_labelApiKey");
    labelApiKey->setFixedWidth(80);
    labelRequestUrl = new kdk::KLabel;
    labelRequestUrl->setAccessibleName("kylin-ai-subsystem-modelconfig_kdk::KLabel_labelRequestUrl");
    labelRequestUrl->setText(tr("RequestUrl"));
    labelRequestUrl->setFixedWidth(80);

    lineeditCustomName = new QLineEdit;
    lineeditCustomName->setAccessibleName("kylin-ai-subsystem-modelconfig_QLineEdit_lineeditAccountName");
    lineeditCustomName->setFixedHeight(36);
    lineeditCustomName->setFocusPolicy(Qt::WheelFocus);
    lineeditCustomName->setPlaceholderText(tr("Required (To distinguish models)"));
    //编辑状态下禁止修改此内容
    if(isEdit){
        lineeditCustomName->setEnabled(false);
    }
    lineeditModelName = new QLineEdit;
    lineeditModelName->setAccessibleName("kylin-ai-subsystem-modelconfig_QLineEdit_lineeditModelName");
    lineeditModelName->setFixedHeight(36);
    lineeditModelName->setPlaceholderText(tr("Optional"));
    lineeditModelName->setFocusPolicy(Qt::WheelFocus);
    passwordEditApi = new kdk::KPasswordEdit(nullptr);
    connect(passwordEditApi, &QLineEdit::textChanged, [=](const QString &text)
    {
       if (text.contains(' '))
       {
          passwordEditApi->setState(LoginState::LoginFailed);
       }
       else
       {
          passwordEditApi->setState(LoginState::Ordinary);
       }
   });
    passwordEditApi->setAccessibleName("kylin-ai-subsystem-modelconfig_kdk::KPasswordEdit_passwordEditApi");
    passwordEditApi->setFocusPolicy(Qt::WheelFocus);
    passwordEditApi->setFixedHeight(36);
    QString tip = QString(tr("Optional (Required for cloud services)"));
    passwordEditApi->setPlaceholderText(tip);
    lineeditRequestUrl = new QLineEdit;
    lineeditRequestUrl->setAccessibleName("kylin-ai-subsystem-modelconfig_QLineEdit_lineeditRequestUrl");
    lineeditRequestUrl->setFixedHeight(36);
    lineeditRequestUrl->setPlaceholderText(tr("Required"));

    QGridLayout *gridLayout = new QGridLayout();
    gridLayout->setVerticalSpacing(8);
    gridLayout->addWidget(labelCustomName, 0, 0);       // 第一行第一列
    gridLayout->addWidget(labelModelName, 1, 0);
    gridLayout->addWidget(labelApiKey, 2, 0);
    gridLayout->addWidget(labelRequestUrl, 3, 0);

    gridLayout->addWidget(lineeditCustomName, 0, 1);             // 第一行第二列
    gridLayout->addWidget(lineeditModelName, 1, 1);
    gridLayout->addWidget(passwordEditApi, 2, 1);
    gridLayout->addWidget(lineeditRequestUrl, 3, 1);


    labelErrorInfo = new QLabel();
    labelErrorInfo->setAccessibleName("kylin-ai-subsystem-modelconfig_QLabel_labelErrorInfo");
    labelErrorInfo->setStyleSheet("color:red; font-size: 14px; font-weight: 400; line-height: 20px;");
    QHBoxLayout *errorInfoLayout = new QHBoxLayout;
    errorInfoLayout->setContentsMargins(90, 0, 0, 0);
    errorInfoLayout->addWidget(labelErrorInfo);
    errorInfoLayout->addStretch();



    buttonCancel = new QPushButton(tr("Cancel"));
    buttonCancel->setAccessibleName("kylin-ai-subsystem-modelconfig_QPushButton_buttonCancel");
    buttonCancel->setFixedHeight(36);
    buttonCancel->setFixedWidth(94);
    buttonCancel->setFocusPolicy(Qt::NoFocus);
    buttonCancel->setProperty("useButtonPalette", true);

    buttonAccept = new QPushButton(tr("Accept"));
    buttonAccept->setAccessibleName("kylin-ai-subsystem-modelconfig_QPushButton_buttonAccept");
    buttonAccept->setFixedHeight(36);
    buttonAccept->setFixedWidth(94);
    buttonAccept->setFocusPolicy(Qt::NoFocus);
    buttonAccept->setEnabled(false);

    QHBoxLayout *buttonLayout = new QHBoxLayout;
    buttonLayout->setContentsMargins(0, 0, 0, 0);
    buttonLayout->addStretch(1);
    buttonLayout->addWidget(buttonCancel);
    buttonLayout->setSpacing(16);
    buttonLayout->addWidget(buttonAccept);


    QVBoxLayout *contentLayout = new QVBoxLayout;
    contentLayout->setContentsMargins(24, 16, 24, 24);
    contentLayout->addLayout(gridLayout);
    contentLayout->addLayout(errorInfoLayout);
    contentLayout->addStretch();
    contentLayout->addLayout(buttonLayout);

    contentWidget = new QWidget;
    contentWidget->setAccessibleName("kylin-ai-subsystem-modelconfig_QWidget_contentWidget");
    contentWidget->setContentsMargins(0, 0, 0, 0);
    contentWidget->setLayout(contentLayout);


    QVBoxLayout *vLayout = new QVBoxLayout;
    vLayout->setContentsMargins(0, 0, 0, 0);
    vLayout->setSpacing(0);
    vLayout->addWidget(contentWidget);
    this->setLayout(vLayout);
}

void PrivateModelConfigDialog::initConnect()
{
    connect(buttonCancel, &QPushButton::clicked, [this](){reject();});
    connect(buttonAccept,&QPushButton::clicked,this,&PrivateModelConfigDialog::accept);

    connect(passwordEditApi, &KPasswordEdit::textChanged, this, [this]() { onPasswordEditChanged(passwordEditApi); });
    connect(passwordEditApi,&KPasswordEdit::textChanged,this,&PrivateModelConfigDialog::updateButtonState);
    connect(lineeditRequestUrl,&QLineEdit::textChanged,this,&PrivateModelConfigDialog::updateButtonState);
    connect(lineeditCustomName,&QLineEdit::textChanged,this,&PrivateModelConfigDialog::updateButtonState);
    connect(lineeditCustomName,&QLineEdit::textChanged,this, [=](const QString &text){

        int totalUnits = 0;
        QString truncatedText;
        for (int i = 0; i < text.length(); ++i) {
            QChar currentChar = text[i];
            // 中文、英文或其他字符占用 1 个单位
            totalUnits += 1;
            // 如果超出最大长度，就截取到此为止
            if (totalUnits > MAX_NAME_COUNT) {
                break;
            }

            truncatedText.append(currentChar);
        }

        if (text != truncatedText) {
            labelErrorInfo->setText(tr("The length must not exceed 32 characters"));
            lineeditCustomName->setText(truncatedText);
        }

        if (totalUnits < MAX_NAME_COUNT) {
            labelErrorInfo->setText("");
        }

        updateButtonState();

    });

}

void PrivateModelConfigDialog::updateButtonState()
{
    bool enableButton = true;
    if(!lineeditCustomName->text().isEmpty() && !lineeditRequestUrl->text().isEmpty())
    {

        if(passwordEditApi->text().contains(" ")  || lineeditRequestUrl->text().contains(" "))
        {
            enableButton = false;
            labelErrorInfo->setText(tr("Cannot contain spaces, please re-enter!"));

        }
        else
        {
            enableButton = true;
           this->labelErrorInfo->setText("");
        }

    }
    else
    {
        if(passwordEditApi->text().contains(" ") || lineeditRequestUrl->text().contains(" "))
        {
            labelErrorInfo->setText(tr("Cannot contain spaces, please re-enter!"));
        }
        else
        {
           this->labelErrorInfo->setText("");
        }
        enableButton = false;
    }
    buttonAccept->setEnabled(enableButton);
    buttonAccept->setProperty("isImportant",enableButton);
}

bool PrivateModelConfigDialog::checkIsHasSpaces()
{
    bool flag = false;
    QList<kdk::KPasswordEdit *> passwordEdits =  this->findChildren<kdk::KPasswordEdit*>();
    if(passwordEdits.isEmpty()) {
        return flag;
    }
    else
    {
        for(int i = 0; i <passwordEdits.size() ;i ++)
        {
            kdk::KPasswordEdit *currentEdit = passwordEdits.at(i);
            if(currentEdit->text().contains(" "))
            {
                //this->m_labelErrorInfo->setText(tr("Cannot contain spaces, please re-enter!"));
                flag = true;
                break;
            }

        }

    }
    return flag;
}


void PrivateModelConfigDialog::accept()
{
    if(checkIsHasSpaces()){//未检查到空格则继续进行
        return;
    }

    PrivateModelConfigWidget *privateModelConfigPage   =  TestAiSubSystem::getPrivateModelConfigPage();

    if (privateModelConfigPage) {
        //判断是否编辑模型
        if (isEdit == false) {
            // 判断是否存在该模型
            if (m_capability == AiCapability::Nlp) {
                if (privateModelConfigPage->m_nlpPrivateModelItemMap.contains(lineeditCustomName->text())) {
                    KyInfo() << "nlp already exist";
                    labelErrorInfo->setText(tr("Duplicate name, please re-enter!"));
                    return;
                }
            } else if (m_capability == AiCapability::Vision) {
                if (privateModelConfigPage->m_nlpPrivateModelItemMap.contains(lineeditCustomName->text())) {
                    KyInfo() << "vision already exist";
                    labelErrorInfo->setText(tr("Duplicate name, please re-enter!"));
                    return;
                }
            } else if (m_capability == AiCapability::Speech) {
                if (privateModelConfigPage->m_nlpPrivateModelItemMap.contains(lineeditCustomName->text())) {
                    KyInfo() << "speech already exist";
                    labelErrorInfo->setText(tr("Duplicate name, please re-enter!"));
                    return;
                }
            }
        }

        PrivateModel model;
        model.capability = m_capability;
        model.modelName =  lineeditCustomName ->text();
        model.modelVersion = lineeditModelName ->text();
        model.apiKey =  passwordEditApi ->text();
        model.apiUrl = lineeditRequestUrl->text();

        if (model.modelName == "" || model.apiUrl == "") {
            if (isEdit == true) {
                showErrorMessage(tr("Model Editing failed"), this);
            } else {
                showErrorMessage(tr("Adding model failed"), this);
            }
            KyInfo() << model.modelName << "必填信息为空，不允许设置模型";
            return;
        }
        ModelConfig mc;
        std::vector<MultiAuthentication> auths = mc.getModelAuthentications(model.modelName.toStdString());
        bool isValueChanged = true;
        for (auto &authen : auths) {
            for (auto &au : authen.authentications) {
                if (au.key == "apiKey") {
                    if (au.value != passwordEditApi->text().toStdString()) {
                        isValueChanged = true;
                    }
                    au.value = passwordEditApi->text().toStdString();
                }
            }
        }
        model.multiAuths = auths;
        if (isEdit == true) {
            // 编辑模型
            bool isCheckSelected = privateModelConfigPage->checkModelSelection(model.capability, model.modelName);
            KyInfo() << "Editing modelname" << model.modelName << "isCheckSelected" << isCheckSelected << "isValueChanged" << isValueChanged;
            bool isCloseEditWindow = privateModelConfigPage->editSelectPrivateModel(model, false, false, isValueChanged, this);
            if (!isCloseEditWindow) {
                return;
            }
        } else {
            // 添加模型
            if (privateModelConfigPage->getModelItemMap(m_capability).count() == 0) {
                // 第一个添加的模型，设为选中
                bool ret = privateModelConfigPage->setSelectPrivateModelConfig(model);
                if (ret == true) {
                    privateModelConfigPage->addModelItem(model);
                    KyInfo() << model.modelName << " 添加选中模型成功";
                } else {
                    showErrorMessage(tr("Adding model failed"), this);
                    KyInfo() << model.modelName << " 添加选中模型失败";
                    return;
                }
            } else {
                // 已有选中模型，只更新验证信息和UI
                bool ret = privateModelConfigPage->addPrivateModel(model);
                if (ret == true) {
                    privateModelConfigPage->addModelItem(model);
                    KyInfo() << model.modelName << " 更新模型验证信息成功";
                } else {
                    showErrorMessage(tr("Adding model failed"), this);
                    KyInfo() << model.modelName << " 更新模型验证信息失败";
                    return;
                }
            }
        }
    }
    labelErrorInfo->setText("");
    return QDialog::accept();
}
