#include "sysusermgt.h"
#include <QDockWidget>
#include <QGraphicsDropShadowEffect>
#include <QToolBar>
#include <QVBoxLayout>
#include <tbaseutil/tdataparse.h>
#include <tbaseutil/tdataresponse.h>
#include <tbaseutil/tenumlist.h>
#include <tbaseutil/ttheme.h>
#include <tbaseutil/tresource.h>
#include <topcore/topclasssqlthread.h>
#include <topcore/topenummanager.h>
#include <topcore/topcore.h>
#include <toputil/t.h>
#include <topcore/topmessagecontroller.h>
#include <topcore/topclasshelper.h>
#include <twidget/tmessagebar.h>
#include <twidget/tmessagebox.h>
#include <twidget/tpagetool.h>
#include <twidget/tsearchentry.h>
#include <twidget/tsplitter.h>
#include <twidget/ttableview.h>
#include <twidget/taccordion.h>
#include "sysusermgtthread.h"

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

    //初始化productCategory配置
    QVariant prodCfg = config("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());
    }

    mBodySplitter = new TSplitter(this);
    this->setCentralWidget(mBodySplitter);
    initNaviView();

    mBodyWidget = new QWidget(this);

    QVBoxLayout *vboxlayout = new QVBoxLayout(mBodyWidget);
    vboxlayout->setMargin(0);
    vboxlayout->setSpacing(0);

    initTableView();

    if (QToolBar *toolbar = qobject_cast<QToolBar*>(uim()->getWidget("MAIN_TOOLBAR"))) {
        toolbar->setWindowTitle(ttr("ToolBar"));
        vboxlayout->addWidget(toolbar, 0);
        mSearchEntry = qobject_cast<TSearchEntry *>(uim()->getWidget("MAIN_TOOLBAR/SEARCH_ENTRY"));
    }
    if (QMenu *table_popup = qobject_cast<QMenu *>(uim()->getWidget("TABLEVIEW_POPUP"))) {
        mTableView->setContextMenu(table_popup);
    }

    vboxlayout->addWidget(mTableView, 1);

    if (QToolBar *toolbar = qobject_cast<QToolBar*>(uim()->getWidget("BOTTOM_TOOLBAR"))) {
        vboxlayout->addWidget(toolbar, 0);
        mPageTool = qobject_cast<TPageTool *>(uim()->getWidget("BOTTOM_TOOLBAR/PAGE_TOOL"));
    }

    QString detailModuleName = config("detail_module_name").toString();
    if (detailModuleName.isEmpty()) {
        detailModuleName = "sys-user";
    }

    mBodySplitter->addWidget(mBodyWidget);

    mDetailView = new SysUser(detailModuleName, config(), this);
    connect(mDetailView, SIGNAL(dataSaved(QVariant)), this, SLOT(onDetailSaved(QVariant)));
    connect(mDetailView, SIGNAL(windowModifyChanged(bool)), SLOT(onDetailChanged()));

    mBodySplitter->addWidget(mDetailView);

    if (mSearchEntry != nullptr) {
        mSearchEntry->setOptionList(TDataParse::headerItem2searchList(mTableView->headerItem()));
        mSearchEntry->setPlaceholderText(ttr("Search %1"));
        connect(mSearchEntry, SIGNAL(search(QString,QVariant)), this, SLOT(refresh()));
        this->setFocusProxy(mSearchEntry);
    }

    if (mPageTool != nullptr) {
        mPageTool->setPageSizeVisible(true);
        connect(mPageTool, SIGNAL(pageChanged(int,int)), this, SLOT(onPageChanged()));
    }

    connect(mTableView->selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)),
            this, SLOT(onSelectionChanged()));

    if (QAction *openAct = this->getAction("open")) {
        connect(mTableView, SIGNAL(activated(QModelIndex)), openAct, SLOT(trigger()));
    }

    mDetailView->resize(TTHEME_DP(config("detail.perfect_size.width", mDetailView->perfectSize().width()).toInt()), mDetailView->height());
    mBodySplitter->setStretchFactor(0, 1);

    this->restoreSizeState();
    this->restoreObjectState(mTableView);

    refreshActionState();
    QTimer::singleShot(0, this, SLOT(refresh()));
}

SysUserMgt::~SysUserMgt()
{
    this->saveSizeState();
    this->saveObjectState(mTableView);
}

void SysUserMgt::refresh(bool iResetPageBol)
{
    t::loading(this);
    TSqlSelectorV2 selector = getSqlSelector(iResetPageBol);
    QVariant data = doThreadWork(new TopClassSqlThread(this), TOPSQLTHREAD_SELECT_ARRAYMAP, QVariant::fromValue(selector));
    unloading();
    TDataResponse dataRes(data.toMap());
    if (dataRes.hasError()) {
        alertError(ttr("Load data failed!"));
    } else {
        fillTableData(dataRes);
        alertOk(ttr("Data loaded"));
    }
    mDetailView->setUid(0);
}

void SysUserMgt::deleteItem(const QVariantList &iIdLst)
{
    //不能删除当前登陆的用户
    if (selectedNames().contains(APP->userName())) {
        alertError(ttr("Current login user can not be deleted!"));
        return;
    }
    //不能删除admin
    if (selectedNames().contains("admin",Qt::CaseInsensitive)) {
        alertError(ttr("Admin can not be deleted!"));
        return;
    }

    QVariant data = doThreadWork(new SysUserMgtThread(this), "DELETE_USER", iIdLst);
    TDataResponse dataRes(data.toMap());
    if (dataRes.hasError()) {
        alertError(ttr("Delete data failed!"), dataRes.errText());
    } else {
        refresh(true);
        alertOk(ttr("Data deleted"));
    }
}

QVariantList SysUserMgt::selectedItems()
{
    return mSelectedLst;
}

TopClassAbs *SysUserMgt::openItem(int iUserIdInt)
{
    QString detailModuleName = "sys-user";
    if (!config("detail_module_name").toString().isEmpty()) {
        detailModuleName = config("detail_module_name").toString();
    }

    SysUser *detail = qobject_cast<SysUser *>(APP->openModule(detailModuleName));
    if (detail != nullptr) {
        detail->setConfig("product_category", this->config("product_category"));
        connect(detail, SIGNAL(dataSaved(QVariant)), this, SLOT(onDetailSaved(QVariant)));
        connect(this, SIGNAL(destroyed()), detail, SLOT(close()));
        detail->setUid(iUserIdInt);
    }

    return detail;
}

void SysUserMgt::newItem()
{
    mBodySplitter->cacheSizes();
    mDetailView->create();
    mDetailView->refreshActionState();
}

bool SysUserMgt::canModify()
{
    return !mDetailView->isDataModified();
}

bool SysUserMgt::isPasswordValidityControl()
{
    QVariantMap dataMap = mDetailView->getData();
    if (dataMap.value("attr_data").toMap().value("password_validity_control") == 1) {
        return true;
    }
    return false;
}

void SysUserMgt::resetPassword()
{
    QVariantList selectedList = mTableView->selectedRowDataMaps();
    if (selectedList.isEmpty()) {
        return;
    }
    loading(ttr("Reset password..."));
    QVariantMap dataMap;
    dataMap["username"] = selectedList.first().toMap()["username"];
    dataMap["password"] = mDetailView->config("default_value.password");
    QVariant data = doThreadWork(new SysUserMgtThread(this), "RESET_PASSWORD", dataMap);
    unloading();
    TDataResponse dataRes(data.toMap());
    if (dataRes.hasError()) {
        alertError(ttr("Reset password failed!"), dataRes.errText());
    } else {
        refresh(true);
        TMessageBox::info(this, ttr("Reset password success!"));
    }
}

void SysUserMgt::resetPasswordValidityDate()
{
    QVariantList selectedList = mTableView->selectedPrimaryKeys();
    if (selectedList.isEmpty()) {
        return;
    }
    QVariantMap dataMap;
    dataMap["id"] = selectedList.first().toString();
    QVariant data = doThreadWork(new SysUserMgtThread(this), "RESET_PASSWORD_VALIDITY_DATE", dataMap);
    TDataResponse dataRes(data.toMap());
    if (dataRes.hasError()) {
        alertError(ttr("Reset password validity date failed!"), dataRes.errText());
    } else {
        refresh(true);
        TMessageBox::info(this, ttr("Reset password validity date success!"));
    }
}

void SysUserMgt::onPageChanged()
{
    refresh(false);
}

void SysUserMgt::onSelectionChanged()
{
    if (mTableView != nullptr) {
        //因为Action的State函数中用到getSelectedList, 所以TableView选择更改时,
        //将其保存至mSelectedLst中, 这样可以加快Action状态的刷新速度;
        mSelectedLst = mTableView->selectedPrimaryKeys();

        int curIdInt = 0;
        if (!mSelectedLst.isEmpty()) {
            curIdInt = mSelectedLst.value(0).toInt();
        }

        if (mDetailView->uid().toInt() != curIdInt) {
            //设置详情模块的上次Uid为当前选择的ID, 这样当如果详情模块处于编辑状态时点取消后显示的当前择的条目内容;
            mDetailView->setLastUid(curIdInt);
            if (!mDetailView->isDataModified()) {
                mDetailView->setUid(curIdInt);
            }
        }

        refreshActionState();
    }
}

void SysUserMgt::onDetailSaved(const QVariant &iUidStr)
{
    this->refresh(false);
    mTableView->selectRow(iUidStr);
}

void SysUserMgt::onDetailChanged()
{
    bool isModified = mDetailView->isDataModified();
    mTableView->setEnabled(!isModified);
    if (isModified) {
        this->showMaskFrame(mBodyWidget);
    } else {
        if (mBodySplitter->sizes().value(0) < 20) {
            mBodySplitter->setWidgetSize(0, mBodySplitter->getCacheSize(0), true);
        }
        this->hideMaskFrame();
    }
    refreshActionState();
}

TSqlSelectorV2 SysUserMgt::getSqlSelector(bool iResetPageBol)
{
    TSqlSelectorV2 selector;
    if (!mTableConf->dbSql.isEmpty()) {
        selector.setTable(QString("(%1) _TEMP_TABLE_").arg(mTableConf->dbSql));
    } else {
        selector.setTable(mTableConf->dbTableName);
    }
    selector.setReturnRowCount(true);
    selector.setField(mTableConf->queryFields);
    selector.setFieldFormat("product_category", "array");

    TopClassHelper::handleSearchPageOnQuery(mSearchEntry, mPageTool, iResetPageBol, &selector);

    if (mNaviView != nullptr && !uiloaderWhere().isEmpty()) {
        selector.addWhere(uiloaderWhere());
    }

    selector.setOrder("id", Qt::DescendingOrder);
    QHeaderView *headerView = mTableView->horizontalHeader();
    if (headerView != nullptr) {
        QString orderField = mTableView->columnName(headerView->sortIndicatorSection());
        if (!orderField.isEmpty() && orderField != "remark") {
            TopClassHelper::handleOrderOnQuery(mTableView, mTableConf, &selector);
        }
    }

    // 当product_category包含 * 时,显示所有
    TSqlWhereCompsiteV2 whereCompsite;
    if (!mProductCategoryLst.contains("*")) {
        whereCompsite.append("product_category",  mProductCategoryLst, "@>");
        whereCompsite.append("product_category",  "{*}");
        whereCompsite.setLogic(TSqlWhereCompsiteV2::Logic_Or);
        selector.whereRef().append(whereCompsite);
    }

    return selector;
}

void SysUserMgt::initTableView()
{
    mTableView = new TTableView(this);
    connect(mTableView->horizontalHeader(), SIGNAL(sortIndicatorChanged(int,Qt::SortOrder)),
            this, SLOT(refresh()));

    mTableConf = new TopClassTableConf;
    TopClassHelper::parseTableConf0(this, "view", mTableConf);

    //TableView Header Items
    mTableView->setDataKeyList(mTableConf->dataKeys);
    mTableView->setPrimaryKey(mTableConf->primaryKey);
    QVariantList headerItem = mTableConf->horizontalHeaders;
    headerItem.prepend(QVariant());
    mTableView->setHeaderItem(headerItem);
}

void SysUserMgt::initNaviView()
{
    TAccordion *accordion = new TAccordion(this);
    accordion->setObjectName("__navi__");
    accordion->setProperty("SS_BG","NAVI");
    accordion->setMinimumWidth(TTHEME_DP(config("navi.min_width", 150).toInt()));
    accordion->setMaximumWidth(TTHEME_DP(config("navi.max_width", 300).toInt()));
    accordion->setAccordionLocation(TAccordion::AccordionLocation::Left);
    QVBoxLayout *naviLayout = new QVBoxLayout(accordion);
    naviLayout->setMargin(0);
    naviLayout->setSpacing(0);
    QLabel *naviLabel = new QLabel(ttr("Navigation"));
    naviLabel->setProperty("SS_TYPE", "SUBHEADER");
    naviLayout->addWidget(naviLabel,0);
    naviLayout->addSpacing(TTHEME_DP(4));
    accordion->expandButton()->setFixedHeight(TTHEME_DP(40));
    accordion->expandButton()->setToolTip(ttr("Show Navigation"));
    accordion->collapseButton()->setToolTip(ttr("Hide Navigation"));
    accordion->setIsExpanded(true);
    mBodySplitter->insertWidget(0,accordion);

    mNaviView = new TUiLoader(this);
    TUiLoader *filterUi = qobject_cast<TUiLoader*>(mNaviView);
    filterUi->setSelf(this);
    filterUi->setScriptEngine(APP->scriptEngine());
    filterUi->setUiStr(ui("navi").toString());

    QFrame *naviWgt = new QFrame(this);
    QVBoxLayout *leftLayout = new QVBoxLayout(naviWgt);
    leftLayout->addWidget(mNaviView);
    QHBoxLayout *leftBtnsLayout = new QHBoxLayout();
    leftBtnsLayout->setMargin(0);
    leftBtnsLayout->setSpacing(10);
    leftLayout->addLayout(leftBtnsLayout);
    QPushButton *resetBtn = new QPushButton(this);
    connect(resetBtn, SIGNAL(clicked(bool)), this, SLOT(onNaviReset()));
    leftBtnsLayout->addWidget(resetBtn);
    resetBtn->setText(ttr("Cancel"));
    resetBtn->setIcon(TRES->icon("rotate-right"));
    QPushButton *filterBtn = new QPushButton(this);
    connect(filterBtn, SIGNAL(clicked(bool)), this, SLOT(refresh()));
    leftBtnsLayout->addWidget(filterBtn);
    filterBtn->setText(ttr("Ok"));
    filterBtn->setIcon(TRES->icon("filter"));
    leftLayout->addStretch(config("navi.is_expanded", false).toBool());
    naviLayout->addWidget(naviWgt);
}

void SysUserMgt::fillTableData(const TDataResponse &iDataRes)
{
    if (mPageTool != nullptr) {
        mPageTool->setRowCount(iDataRes.dataCount(), true);
    }
    QVariantList dataLst = iDataRes.data().toList();
    TopClassHelper::formatTableData(this, mTableConf, dataLst);
    mTableView->loadData(dataLst);
}

QStringList SysUserMgt::selectedNames()
{
    QStringList retLst;
    for (QVariant item : mTableView->selectedRowDataMaps()) {
        retLst << item.toMap().value("username").toString();
    }
    return retLst;
}

QString SysUserMgt::uiloaderWhere()
{
    if (mNaviView == nullptr) {
        return "";
    }

    auto filterDataMap = mNaviView->getAllValues().toVariant().toMap();
    QString searchSql;
    QMapIterator<QString, QVariant> iter(filterDataMap);
    while (iter.hasNext()) {
        iter.next();
        QString key = iter.key();
        QString value = iter.value().toString();
        if (value.isEmpty()) {
            continue;
        }
        auto obj = mNaviView->getObject(key);
        if (obj != nullptr) {
            QVariantMap userData = obj->property("tui_user_data").toMap();
            if (userData.contains("field_name")) {
                key = userData.value("field_name").toString();
            }
            QString operatorStr = "=";
            if (userData.contains("operator")) {
                operatorStr = userData.value("operator").toString();
            }
            if (operatorStr.compare("like", Qt::CaseInsensitive) == 0 ||
                    operatorStr.compare("ilike", Qt::CaseInsensitive) == 0) {
                value = QString("'%%1%'").arg(value);
            } else if (operatorStr.compare("in", Qt::CaseInsensitive) == 0) {
                value = QString("(%1)").arg(value);
            } else {
                if (iter.value().type() == QVariant::String) {
                    value = QString("'%1'").arg(value);
                }
            }
            QString searchStr = QString("%1 %2 %3").arg(key).arg(operatorStr).arg(value);
            if (!searchSql.isEmpty()) {
                searchSql.append(" and ");
            }
            searchSql.append(searchStr);
        }
    }
    return searchSql;
}

void SysUserMgt::onNaviReset()
{
    mNaviView->clearValues();
    refresh(true);
}