#include "sysusermgt.h"
#include <QGraphicsDropShadowEffect>
#include <QToolBar>
#include <QVBoxLayout>
#include <tbaseutil/tdataparse.h>
#include <tbaseutil/tdataresponse.h>
#include <tbaseutil/tenumlist.h>
#include <tbaseutil/ttheme.h>
#include <tbaseutil/tlogger.h>
#include <tdatabaseutil/tsqlconnectionpoolv2.h>
#include <tdatabaseutil/tsqlqueryv2.h>
#include <tdatabaseutil/tsqlselectorv2.h>
#include <topcore/topclasssqlthread.h>
#include <topcore/topenummanager.h>
#include <topcore/topcore.h>
#include <toputil/t.h>
#include <twidget/ttableview.h>
#include <twidget/tsearchentry.h>
#include <twidget/tpagetool.h>
#include <twidget/tadvancedquery.h>
#include <twidget/tmessagebar.h>
#include <twidget/tcategorytreeview.h>
#include <twidget/ttableviewdialog.h>
#include <twidget/tmessagebox.h>
#include <twidget/taccordion.h>
#include <twidget/tsplitter.h>
#include <twidget/tscrollarea.h>
#include <twidget/ttabwidget.h>
#include <tbaseutil/tresource.h>
#include <tbaseutil/tdataparse.h>


SysUserMgt::SysUserMgt(const QString &iModuleNameStr,
                       const QVariantMap &iUrlPars,
                       QWidget *iParent):
    TopClassAbs(iParent)
{
    initModule(iModuleNameStr, iUrlPars);
    QString licenseKey = config("sys_common").toString();
    if (!licenseKey.isEmpty()) {
        setLicenseKey(licenseKey);
    }
    QStringList langLst = config("lang.conf").toStringList();
    for (const auto &lang : langLst) {
        appendLanguage(lang);
    }
    if (isHookExists("afterModuleInit")) {
        callHooks("afterModuleInit");
    }
    TopClassHelper::parseTableConf0(this, "view", &mTableConf);
    initTableView();
    connect(this, SIGNAL(detailSaved(QVariant)),
            this, SLOT(onDetailSaved(QVariant)));
    connect(this, SIGNAL(isDetailModifiedChanged(bool)),
            this, SLOT(onDetailChanged(bool)));
    connect(this, SIGNAL(detailUidChanged(QString)),
            this, SLOT(refreshDetail(QString)));
    if (isHookExists("afterViewInit")) {
        callHooks("afterViewInit");
    }
    restoreSizeState();
    restoreObjectState(mBodySplitter);
    restoreObjectState(mTableView);

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

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

void SysUserMgt::setData(const QVariantMap &iDataMap)
{
    mDetailView->loadValues(iDataMap, false);

    if (iDataMap.contains("username")) {
        setTitle(ttr("User-%1").arg(iDataMap.value("username").toString()));
    }
}


void SysUserMgt::reload()
{
    setDetailUid(mLastDetailUid.isEmpty() ? mDetailUid : mLastDetailUid, true);
}

bool SysUserMgt::DetailModified() const
{
    return IsDetailchange;
}

void SysUserMgt::setIsDetailModified(bool iIsDetailModified)
{
    if (IsDetailchange == iIsDetailModified) {
        return;
    }
    IsDetailchange = iIsDetailModified;
    emit isDetailModifiedChanged(iIsDetailModified);
}

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

QString SysUserMgt::detailUid() const
{
   return mDetailUid;
}

void SysUserMgt::setDetailUid(const QString &iUid, bool iForceRefresh)
{
   if (iForceRefresh || mDetailUid != iUid) {
       mDetailUid = iUid;
       emit detailUidChanged(iUid);
    }
}

void SysUserMgt::newItem()
{
    mLastDetailUid = mDetailUid;
    setDetailUid(QString());
    setIsDetailModified(true);
}
/*!
 * 保存详细信息表里的数据信息
 */
void SysUserMgt::saveItem()
{
    //验证有效性
    QVariantList errLst = mDetailView->validateAll("COMMIT", true, "ERROR");
    if (!errLst.isEmpty()) {
        QStringList errStrLst;
        for (QVariant err : errLst) {
            errStrLst.append(err.toMap().value("text").toString());
        }
        alertError(ttr("saved failed!"), errStrLst.join("\n"));
        return;
    }

    //使用TopClassTableConf类对象配置各项信息
    TSqlInserterV2 insertor;
    insertor.setTable(mTableConf.dbTableName);
    QVariantMap saveData;
    QMap<QString, QString> updatePolicy;
    TopClassHelper::fetchSaveFieldsFromUi(mDetailView, saveData, updatePolicy);
    insertor.addUniqueField(mTableConf.primaryKey);
    insertor.setAutoIncrementField(mTableConf.primaryKey);
    saveData.insert(mTableConf.primaryKey, mDetailUid);

    if (config("view.data_set.db_filter").type() == QVariant::Map) {
          QVariantMap dbFilterMap = config("view.data_set.db_filter").toMap();
          QMapIterator<QString, QVariant> i(dbFilterMap);
          while (i.hasNext()) {
              i.next();
              saveData.insert(i.key(), i.value());      //向saveData里插入各项数据的键和值
          }
    }
    QVariantMap defaultValueMap;
    QVariantMap resultmap;
    defaultValueMap = defaultValueMap.unite(config("default_value").toMap());   //去module里拿默认的的信息
    QString password = defaultValueMap.value("password").toString();
    resultmap = TDataParse::mergeVariantMap(saveData, defaultValueMap);
    resultmap.insert("password", TDataParse::getVariantMd5(password));
    insertor.setData(resultmap);
    QStringList fields = resultmap.keys();
    fields.removeOne(mTableConf.primaryKey);
    insertor.setField(fields);
    {
        QMapIterator<QString, QString> i(updatePolicy);
        while (i.hasNext()) {
            i.next();
            insertor.setUpdatePolicy(i.key(), i.value());
        }
    }
    TError err;
    QVariant result = runSqlQueryOnThreadSync(TOPSQLTHREAD_REPLACE_ROW,
                                              QVariant::fromValue(insertor),
                                              &err);
    if (err.isValid()) {
        alertError(ttr("Save data failed!"), err.text());
        return;
    }
    emit detailSaved(result);
    setIsDetailModified(false);
    alertOk(ttr("Data saved"));
}

/*!
 * \删除用户
 */
void SysUserMgt::removeUser(const QVariantList &iItems)
{
    if (mTableConf.dbDelFlagKey.isEmpty()) {
        TSqlDeleterV2 deleter;
        deleter.setTable(mTableConf.dbTableName);
        deleter.setWhere(mTableConf.primaryKey, iItems);
        TError err;
        runSqlQueryOnThreadSync(TOPSQLTHREAD_DELETE_ROW,
                                QVariant::fromValue(deleter),
                                &err);
        if (err.isValid()) {
            alertError(ttr("Delete data failed!"), err.text());
        } else {
            refresh(true);
            alertOk(ttr("Data deleted"));
        }
    } else {
        TSqlUpdaterV2 updater;
        updater.setTable(mTableConf.dbTableName);
        updater.setWhere(mTableConf.primaryKey, iItems);
        updater.setData(QVariantMap {{mTableConf.dbDelFlagKey, 1}});
        TError err;
        runSqlQueryOnThreadSync(TOPSQLTHREAD_UPDATE_ROW,
                                QVariant::fromValue(updater),
                                &err);
        if (err.isValid()) {
            alertError(ttr("Delete data failed!"), err.text());
        } else {
            refresh(true);
            alertOk(ttr("Moved to recycle bin"));
        }
    }
}

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

void SysUserMgt::onSelectionChanged()
{
    mSelectedItems = mTableView->selectedPrimaryKeys();
    QString curId;
    if (!mSelectedItems.isEmpty()) {
        curId = mSelectedItems.first().toString();
    }
    if (mDetailUid != curId) {
        mLastDetailUid = curId;
        if (!IsDetailchange) {
            setDetailUid(curId);
        }
    }
    refreshActionState();
}

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

void SysUserMgt::onDetailDataChanged()
{
    setIsDetailModified(true);
}

void SysUserMgt::onDetailChanged(bool iIsDetailModified)
{   
    mTableView->setEnabled(!iIsDetailModified);
    if (iIsDetailModified) {
        showMaskFrame(mBodyWidget);
    } else {
        hideMaskFrame();
    }
    refreshActionState();
}

/*!
 * 刷新表格
 */
void SysUserMgt::refresh(bool iResetPage)
{
    TSqlSelectorV2 selector;
    if (!mTableConf.dbSql.isEmpty()) {
        selector.setTable(mTableConf.dbSql);
    } else if (!mTableConf.dbTableName.isEmpty()) {
        selector.setTable(mTableConf.dbTableName);
    } else {
        alertError(ttr("dbSql and dbtablename isempty!"));
        return;         //dbSql和dbTableName为空则返回不做处理
    }
    selector.setField(mTableConf.queryFields);
    selector.setFieldFormat(mTableConf.fieldFormatMap);

    selector.setReturnRowCount(true);
    TopClassHelper::handleSearchPageOnQuery(mSearchEntry, mPageTool, iResetPage, &selector);
    TopClassHelper::handleOrderOnQuery(mTableView, &mTableConf, &selector);
    if (!mTableConf.dbDelFlagKey.isEmpty()) {
        selector.addWhere(QString("%1 = 0 OR %1 IS NULL").arg(mTableConf.dbDelFlagKey));
    }
    if (!mTableConf.dbFilter.isEmpty()) {
        selector.addWhere(mTableConf.dbFilter);
    }
    t::loading(this);
    QVariant data = doThreadWork(new TopClassSqlThread(this), TOPSQLTHREAD_SELECT_ARRAYMAP, QVariant::fromValue(selector));
    unloading();
    TDataResponse response(data.toMap());
    if (response.hasError()) {
        alertError(ttr("Load data failed!"));
    } else {
        if (mPageTool != nullptr) {
            mPageTool->setRowCount(response.dataCount(), true);
        }
        QVariantList tableData = response.data().toList();
        TopClassHelper::formatTableData(this, &mTableConf, tableData);
        if (isHookExists("handleTableData")) {
            tableData = callHooksQuick("handleTableData", QVariantList() << QVariant(tableData)).toVariant().toList();
        }
        mTableView->loadData(tableData);
        mTableView->adjustViewSpan(mTableConf.mergeKeys);
        mSelectedItems.clear();
        setDetailUid(QString());
        alertOk(ttr("Data loaded"));
    }
}

/*!
 * 刷新详细表单
 */
void SysUserMgt::refreshDetail(const QString &iUid)
{
    if (iUid.isEmpty()) {
        mDetailView->loadValues(QVariantMap(), true);
    } else {
        TSqlSelectorV2 selector;
        if (!mTableConf.dbSql.isEmpty()) {
            selector.setTable(mTableConf.dbSql);
        } else if (!mTableConf.dbTableName.isEmpty()) {
            selector.setTable(mTableConf.dbTableName);
        } else {
            return;
        }
        selector.setField(mTableConf.queryFields);
        selector.setWhere(mTableConf.primaryKey, iUid);
        selector.setFieldFormat(mTableConf.fieldFormatMap);
        TError err;
        QVariant data = runSqlQueryOnThreadSync(TOPSQLTHREAD_SELECT_MAP,
                                                QVariant::fromValue(selector),
                                                &err);
        if (err.isValid()) {
            alertError(ttr("Load data failed!"), err.text());
            return;
        }
        QVariantMap dataMap = data.toMap();
        mDetailView->loadValues(dataMap, true);
    }
    alertOk(ttr("Data loaded"));
    setIsDetailModified(false);
}

/*!
 * 初始化界面
 */
void SysUserMgt::initTableView()
{
    mBodySplitter = new TSplitter(this);
    mBodySplitter->setObjectName("mBodySplitter");
    setCentralWidget(mBodySplitter);
    mBodyWidget = new TSplitter(this);
    mBodySplitter->addWidget(mBodyWidget);

    mBodyWgt = new QWidget(this);
    QVBoxLayout *bodyLayout = new QVBoxLayout(mBodyWgt);
    bodyLayout->setMargin(0);
    bodyLayout->setSpacing(0);
    mBodyWidget->addWidget(mBodyWgt);

    mTableView = new TTableView(this);
    mTableView->setObjectName("__view__");
    mTableView->setHeaderPopupEnabled(true);
    connect(mTableView->horizontalHeader(), SIGNAL(sortIndicatorChanged(int,Qt::SortOrder)),
            this, SLOT(refresh()));
    connect(mTableView->selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)),
            this, SLOT(onSelectionChanged()));
    connect(mTableView->selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)),
            this, SIGNAL(selectionChanged()));
    mTableView->setDataKeyList(mTableConf.dataKeys);
    mTableView->setPrimaryKey(mTableConf.primaryKey);
    QVariantList headerItems = mTableConf.horizontalHeaders;
    headerItems.prepend(QVariant());
    mTableView->setHeaderItem(headerItems);

    if (QToolBar *toolbar = qobject_cast<QToolBar*>(uim()->getWidget("MAIN_TOOLBAR"))) {
        bodyLayout->addWidget(toolbar, 0);
        mSearchEntry = qobject_cast<TSearchEntry *>(uim()->getWidget("MAIN_TOOLBAR/SEARCH_ENTRY"));
        if (mSearchEntry != nullptr) {
            connect(mSearchEntry, SIGNAL(search(QString,QVariant)), this, SLOT(refresh()));
            mSearchEntry->setOptionList(TDataParse::headerItem2searchList(mTableView->headerItem()));
            mSearchEntry->setPlaceholderText(ttr("Search %1"));
        }
    }
    if (QMenu *tablePopup = qobject_cast<QMenu *>(uim()->getWidget("TABLEVIEW_POPUP"))) {
        mTableView->setContextMenu(tablePopup);
    }

    bodyLayout->addWidget(mTableView, 1);

    if (QToolBar *toolbar = qobject_cast<QToolBar*>(uim()->getWidget("BOTTOM_TOOLBAR"))) {
        bodyLayout->addWidget(toolbar, 0);
        mPageTool = qobject_cast<TPageTool *>(uim()->getWidget("BOTTOM_TOOLBAR/PAGE_TOOL"));
        if (mPageTool != nullptr) {
            mPageTool->setPageSizeVisible(true);
            connect(mPageTool, SIGNAL(pageChanged(int,int)), this, SLOT(onPageChanged()));
        }
    }
    QWidget *detailWgt = new QWidget(this);
    QVBoxLayout *detailLayout = new QVBoxLayout(detailWgt);
    detailLayout->setSpacing(0);
    detailLayout->setMargin(0);

    if (QToolBar *toolbar = qobject_cast<QToolBar*>(uim()->getWidget("DETAIL_TOOLBAR"))) {
        detailLayout->addWidget(toolbar, 0);
    }
    mDetailView = new TUiLoader(this);

    connect(mDetailView, SIGNAL(dataChanged()), this, SLOT(onDetailDataChanged()));
    mDetailView->setProperty("SS_BG", "PANEL");
    mDetailView->setSelf(this);
    mDetailView->setScriptEngine(APP->scriptEngine());
    mDetailView->setUiStr(ui("detail").toString());
    detailLayout->addWidget(mDetailView);

    if (!ui("detail").isNull()) {
        mBodySplitter->addWidget(detailWgt);
        mBodySplitter->setStretchFactor(0, 1);
        mBodySplitter->setSizes(QList<int>{1, config("detail.perfect_width", 600).toInt()});
    } else {
        detailWgt->setVisible(false);
    }
}