#include "sysuser.h"
#include <QGraphicsDropShadowEffect>
#include <QResizeEvent>
#include <QToolBar>
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <tbaseutil/tdataresponse.h>
#include <tbaseutil/tdataparse.h>
#include <tbaseutil/ttheme.h>
#include <tbaseutil/tenumlist.h>
#include <tdatabaseutil/tsqlselectorv2.h>
#include <topcore/topcore.h>
#include <topcore/topclasssqlthread.h>
#include <topcore/topenummanager.h>
#include <toputil/t.h>
#include <twidget/tmessagebar.h>
#include <twidget/ttableview.h>
#include <twidget/ttableviewdialog.h>
#include <twidget/tuiloader.h>
#include "sysuserthread.h"

SysUser::SysUser(const QString &iModuleNameStr, const QVariantMap &iUrlPars, QWidget *iParent)
    : TopClassAbs(iParent)
{
    this->setLicenseKey("sys_common");
    this->initModule(iModuleNameStr, iUrlPars);

    QVariant prodCfg = iUrlPars.value("product_category");
    if (prodCfg.type() == QVariant::List || prodCfg.type() == QVariant::StringList) {
        for (QVariant row : prodCfg.toList()) {
            mProductCategoryLst.append(row.toString());
        }
    } else if (!prodCfg.toString().isEmpty()) {
        mProductCategoryLst.append(prodCfg.toString());
    }

    if (mProductCategoryLst.isEmpty()) {
        mProductCategoryLst.append(APP->productCategory());
    }

    QWidget *centerWgt = new QWidget(this);
    this->setCentralWidget(centerWgt);
    QVBoxLayout *centerLayout = new QVBoxLayout(centerWgt);
    centerLayout->setMargin(0);
    centerLayout->setSpacing(0);

    if (QToolBar *toolbar = qobject_cast<QToolBar *>(uim()->getWidget("MAIN_TOOLBAR"))) {
        centerLayout->addWidget(toolbar, 0);
    }

    mBodyLayout = new QHBoxLayout();
    centerLayout->addLayout(mBodyLayout, 1);
    mBodyLayout->setMargin(TTHEME_DP(16));
    mBodyLayout->setSpacing(0);

    mUiLoader = new TUiLoader(this);
    mUiLoader->setScriptEngine(APP->scriptEngine());
    mUiLoader->setSelf(this);
    mUiLoader->setMaximumWidth(TTHEME_DP(config("maximum_size.width", 800).toInt()));

    mUiLoader->setProperty("SS_BG", "PANEL");
    mUiLoader->setProperty("SS_BORDER", 1);

    mBodyLayout->addStretch(1);
    mBodyLayout->addWidget(mUiLoader, 99999);
    mBodyLayout->addStretch(1);

    mUiLoader->setUiStr(ui("user-info").toString());
    mRoleTableView = qobject_cast<TTableView*>(mUiLoader->getObject("ROLE_LIST"));

    connect(mRoleTableView->selectionModel(), &QItemSelectionModel::selectionChanged, this, [=](){
        mUiLoader->refreshState();
    });
    connect(mUiLoader, SIGNAL(dataChanged()), this, SLOT(setDataModified()));

    //恢复窗体尺寸及布局;
    restoreSizeState();

    //当URL传入包含UID时, 在initModule()中会自动赋值给UID;
    //在界面初始化完成后执行uidChangeEvent, 填充界面数据;
    uidChangeEvent(this->uid());

    //刷新Action状态;
    refreshActionState();
}

SysUser::~SysUser()
{
    saveSizeState();
}

void SysUser::reload()
{
    QString uidStr = lastUid().isEmpty() ? uid() : lastUid();
    setUid(uidStr, true);
}

void SysUser::copy()
{
    setLastUid(this->uid());
    setUid(0, false);
    QVariantMap data;
    data.insert("username", "");
    data.insert("id", "");
    data.insert("contcat_id", "");
    data.insert("password", config("default_value").toMap().value("password").toString());
    setData(data);
    setTitle(ttr("New User"));
    setDataModified();
}

void SysUser::create()
{
    setLastUid(this->uid());
    setUid(0, true);
    QVariantMap defaultValueMap;
    defaultValueMap.insert("product_category", mProductCategoryLst);
    defaultValueMap = defaultValueMap.unite(config("default_value").toMap());
    mUiLoader->setState("status", "disable");
    setData(defaultValueMap);
    setDataModified();
}

void SysUser::clearData()
{
    mUiLoader->loadValues(QVariantMap(), true);
    if (mRoleTableView != nullptr) {
        mRoleTableView->loadData(QVariantList());
    }
}

void SysUser::setData(const QVariantMap &iDataMap)
{
    mUiLoader->loadValues(iDataMap, false);
    if (iDataMap.contains("username")) {
        setTitle(ttr("User-%1").arg(iDataMap.value("username").toString()));
    }
}

QVariantMap SysUser::getData() const
{
    QVariantMap dataMap = mUiLoader->getAllValues(true).toVariant().toMap();
    QStringList keys = dataMap.keys();
    for (QString key: keys) {
        if (key.contains(".")) {
            QString keyA = key.split(".").first();
            QString keyB = key.split(".").last();
            QVariantMap map = dataMap.value(keyA, QVariantMap()).toMap();
            map.insert(keyB, dataMap.value(key));
            dataMap.insert(keyA, map);
            dataMap.remove(key);
        }
    }
    if (this->uid().toInt() == 0) {
        QVariantMap attrData = dataMap.value("attr_data").toMap();
        attrData.insert("effective_date", APP->getServerToday());
        dataMap.insert("attr_data", attrData);
    }
    if (mRoleTableView != nullptr) {
        dataMap.insert("ROLE_LIST", mRoleTableView->allDataMap());
    }

    if (dataMap.value("product_category").toStringList().isEmpty()) {
        dataMap.insert("product_category", mProductCategoryLst);
    }

    dataMap.insert("id", this->uid());
    return dataMap;
}

void SysUser::saveData()
{
    QVariantList errLst = mUiLoader->validateAll("COMMIT", true, "ERROR");
    if (!errLst.isEmpty()) {
        QStringList errStrLst;
        for (QVariant err : errLst) {
            errStrLst.append(err.toMap().value("text").toString());
        }
        alertError(ttr("Saving data failed!"), errStrLst.join("\n"));
        return;
    }
    t::saving(this);
    QVariantMap saveData = getData();
    if (isHookExists("handleSaveData")) {
        saveData = callHooksQuick("handleSaveData", QVariantList()<<saveData).toVariant().toMap();
    }
    QVariant data = doThreadWork(new SysUserThread(this), "SAVE_DATA", saveData);
    unloading();
    TDataResponse dataRes(data.toMap());
    if (dataRes.hasError()) {
        alertError(ttr("Save data failed!"), dataRes.errText());
    } else {
        setUid(dataRes.data().toInt());
        emit dataSaved(this->uid());
        APP->notify("sys-user-save");
        alertOk(ttr("Data saved"));
    }
}

void SysUser::showAddRoleDialog()
{
    if (mRoleTableView == nullptr) {
        return;
    }

    TTableViewDialog *dialog = new TTableViewDialog(this);
    dialog->resize(280, 400);
    dialog->setTitle(ttr("Add Role"));
    dialog->setButtons(QStringList()
                       << ttr("Ok") + ":Ok:Yes"
                       << ttr("Cancel") + ":Cancel:Cancel"
                       << ttr("Clear All") + ":UnselectAll:ResetRole");

    QVariantList headerItems;
    headerItems << QVariant();
    headerItems << TDataParse::variantList2Map(
                       QVariantList() << "name" << "name" << "display" << ttr("Role Name") <<
                       "displayRole" << "$name" << "resizeMode" << "Interactive" );
    headerItems << TDataParse::variantList2Map(
                       QVariantList() << "name" << "description" << "display" << ttr("Description") <<
                       "displayRole" << "$description" << "resizeMode" << "Stretch");

    dialog->setPrimaryKey("id");
    dialog->setDataKeyList(QStringList() << "id" << "name" << "description");
    dialog->setHeaderItem(headerItems);
    dialog->setSearchKeys(QStringList() << "name" << "description");
    dialog->setSelectionMode(QAbstractItemView::MultiSelection);
    dialog->tableView()->horizontalHeader()->setStretchLastSection(true);

    TSqlSelectorV2 sqlSelector;
    sqlSelector.setTable("sys_role");
    sqlSelector.fieldRef() << "id" << "name" << "description";
    TSqlWhereCompsiteV2 whereCompsite;
    if (!mProductCategoryLst.contains("*")) {
        whereCompsite.append("product_category",  mProductCategoryLst, "@>");
        whereCompsite.append("product_category",  "{*}");
        whereCompsite.setLogic(TSqlWhereCompsiteV2::Logic_Or);
        sqlSelector.whereRef().append(whereCompsite);
    }
    sqlSelector.setOrder("name", Qt::AscendingOrder);
    sqlSelector.whereRef().setLogic(TSqlWhereCompsiteV2::Logic_Or);

    QVariant data = doThreadWork(new TopClassSqlThread(this), TOPSQLTHREAD_SELECT_ARRAYMAP, QVariant::fromValue(sqlSelector));
    TDataResponse dataRes(data.toMap());
    QVariantList allRoles = dataRes.data().toList();

    QVariantList tableDataLst;
    QVariantList existLst = mRoleTableView->allPrimaryKey();
    for (QVariant row : allRoles) {
        QVariantMap rowMap = row.toMap();
        if (!existLst.contains(rowMap.value("id"))) {
            tableDataLst.append(row);
        }
    }
    dialog->loadData(tableDataLst);

    QVariantList selLst = dialog->run();
    QModelIndexList indexs = mRoleTableView->appendRows(selLst);
    mRoleTableView->unselectAll();
    mRoleTableView->selectRows(indexs);
    mRoleTableView->scrollToBottom();
}

void SysUser::uidChangeEvent(const QString &iUidStr)
{
    if (iUidStr.toInt() == 0) {
        setTitle(ttr("New User"));
        clearData();
    } else {
        t::loading(this);
        QVariant data = doThreadWork(new SysUserThread(this), "LOAD_DATA", QVariant(this->uid()));
        unloading();
        TDataResponse dataRes(data.toMap());
        if (dataRes.hasError()) {
            alertError(ttr("Load data failed!"), dataRes.errText());
        } else {
            clearData();
            QVariantMap dataMap = dataRes.data().toMap();
            QVariantMap attrData = dataMap.value("attr_data").toMap();
            for (QString key: attrData.keys()) {
                dataMap.insert("attr_data." + key, attrData.value(key));
            }
            setData(dataMap);
            alertOk(ttr("Data loaded"));
        }
    }
    mUiLoader->setState("status", "enable");
    setDataModified(false);
}

void SysUser::resizeEvent(QResizeEvent *iEvent)
{
    QSize size = iEvent->size();
    if (size.width() > this->perfectSize().width()) {
        mBodyLayout->setMargin(TTHEME_DP(16));
        mUiLoader->setProperty("SS_BORDER", 1);
        mUiLoader->setStyleSheet(".Q{}");
    } else {
        mBodyLayout->setMargin(0);
        mUiLoader->setProperty("SS_BORDER", 0);
        mUiLoader->setStyleSheet(".Q{}");
    }
}