//
// Created by Krad on 2021/11/10.
//
#include "AccountFormDialog.h"
#include "ChangePasswordFormDialog.h"
#include <QVBoxLayout>
#include <QLabel>
#include <QUuid>
#include <QDebug>
#include <QToolButton>
#include <QPushButton>
#include <QLineEdit>
#include "event/EventCenter.h"
#include "log/UserOperationLog.h"
#include "db/SQLHelper.h"
#include "models/User.h"
#include "components/SlidePickerBox.h"
#include "SelectDialog.h"
#include "AlertDialog.h"

AccountFormDialog::AccountFormDialog(QWidget* parent, AccountEditMode mode, Qt::WindowFlags f) : GUIFormBaseDialog(parent, f) {
    m_mode = mode;
    QVBoxLayout *layout = new QVBoxLayout(formWidget);
    layout->setSpacing(10);
    // add title
    QLabel *lbl_title = new QLabel(this);
    lbl_title->setAlignment(Qt::AlignCenter);
    lbl_title->setText(tr("Account"));
    lbl_title->setObjectName("title");
    layout->addWidget(lbl_title);

    //add usercode
    QLabel *lbl_UserCode = new QLabel(this);
    lbl_UserCode->setText(tr("User ID"));
    le_UserCode = new QLineEdit(this);
    le_UserCode->setPlaceholderText(tr("Input User ID"));
    if (m_mode != New)le_UserCode->setEnabled(false);
    layout->addWidget(lbl_UserCode);
    layout->addWidget(le_UserCode);
    QLabel *lbl_endline1 = new QLabel(this);
    lbl_endline1->setObjectName("endline");
    layout->addWidget(lbl_endline1);

    //add username
    QLabel *lbl_UserName = new QLabel(this);
    lbl_UserName->setText(tr("Name"));
    le_UserName = new QLineEdit(this);
    le_UserName->setPlaceholderText(tr("Input User name"));
    layout->addWidget(lbl_UserName);
    layout->addWidget(le_UserName);
    QLabel *lbl_endline2 = new QLabel(this);
    lbl_endline2->setObjectName("endline");
    layout->addWidget(lbl_endline2);

    // add new mode
    if (m_mode == New) {
        //add password
        QLabel *lbl_Pwd = new QLabel(this);
        lbl_Pwd->setText(tr("Password"));
        layout->addWidget(lbl_Pwd);
        le_Pwd = new QLineEdit(this);
        le_Pwd->setPlaceholderText(tr("Input password"));
        le_Pwd->setEchoMode(QLineEdit::Password);
        layout->addWidget(le_Pwd);
        m_RoleID = User::getRoleID("doctor");
        QLabel *lbl_endline3 = new QLabel(this);
        lbl_endline3->setObjectName("endline");
        layout->addWidget(lbl_endline3);
    }


    //add Comment
    QLabel *lbl_Comment = new QLabel(this);
    lbl_Comment->setText(tr("Comment"));
    le_Comment = new QLineEdit(this);
    layout->addWidget(lbl_Comment);
    layout->addWidget(le_Comment);
    QLabel *lbl_endline0 = new QLabel(this);
    lbl_endline0->setObjectName("endline");
    layout->addWidget(lbl_endline0);

    lbl_error = new QLabel(this);
    lbl_error->setObjectName("warn");
    lbl_error->setVisible(false);
    layout->addWidget(lbl_error);


    QHBoxLayout* hlayout = new QHBoxLayout;
    layout->addLayout(hlayout);

    //add logout
//    QLabel *lbl_Logout = new QLabel(this);
//    lbl_Logout->setText(tr("Logout"));
    if (m_mode == Self)
    {
        QToolButton *btn_Logout = new QToolButton(this);
        btn_Logout->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
        btn_Logout->setIcon(QIcon(":/icons/logout.png"));
        btn_Logout->setIconSize({30, 30});
        btn_Logout->setText(tr("Logout"));
        btn_Logout->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Fixed);
        btn_Logout->setObjectName("editvalBtn");

        hlayout->addWidget(btn_Logout);
        connect(btn_Logout, &QAbstractButton::clicked, [=]() {
            this->accept();
            LOG_USER_OPERATION(Logout);
            EventCenter::Default()->triggerEvent(GUIEvents::RequestLogin, nullptr, nullptr);
        });
    }

    // load current user data
    if (m_mode == Self && User::Current()) {
        le_UserCode->setText(User::Current()->getUserCode());
        le_UserName->setText(User::Current()->getUserName());
        m_UserID = User::Current()->getUserID();
        m_UserPwd = User::Current()->getPassword();
    }
    if (m_mode != New) {
        btn_Pwd = new QToolButton(this);
        btn_Pwd->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
        btn_Pwd->setObjectName("editvalBtn");
        btn_Pwd->setIcon(QIcon(":/icons/edit.png"));
        btn_Pwd->setIconSize({30, 30});
        btn_Pwd->setText(m_mode == Self ? tr("Change Password") : tr("Reset Password"));
        btn_Pwd->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
        hlayout->addWidget(btn_Pwd);
        QLabel *lbl_endline9 = new QLabel(this);
        lbl_endline9->setFixedHeight(2);
        lbl_endline9->setObjectName("endline");
        layout->addWidget(lbl_endline9);
        if (m_mode == Self) {
            connect(btn_Pwd, &QPushButton::clicked, [=]() {
                ChangePasswordFormDialog dia(this->parentWidget());
                dia.setWindowModality(Qt::WindowModal);
                dia.exec();
            });
        } else {
            connect(btn_Pwd, &QAbstractButton::clicked, [=]() {
                AlertDialog dialog(this);
                dialog.setButtonMode(OkAndCancel);
                dialog.setWindowModality(Qt::WindowModal);
                dialog.setAlertMessage(tr("Reset password to \"123456\" ?"));
                if (dialog.exec() == Accepted) {
                    User user;
                    dialog.setButtonMode(OkOnly);
                    if (!User::getUser(m_UserID, user)) {
                        dialog.setAlertMessage(tr("Inner error, can't find reference user!"));
                        dialog.exec();
                        return;
                    }
                    if (!user.resetPassword()) {
                        dialog.setAlertMessage(tr("Submit change to database fail!"));
                        dialog.exec();
                    }
                }
            });
        }
    }

    connect(le_Comment, &QLineEdit::textChanged, [=](const QString &text) {
        commentChanged = true;
    });
    connect(le_UserName, &QLineEdit::textChanged, [=](const QString &text) {
        m_NewUserName = text;
        userNameChanged = true;
    });
}

AccountFormDialog::~AccountFormDialog() {

}

bool AccountFormDialog::updateReferenceData() {
	if (m_mode == Self) {
		if (!this->userNameChanged && !this->commentChanged) return true;
		if (!this->userNameChanged) {
			if (m_NewUserName.isEmpty()) {
				warn(tr("User Name can't be empty!"));
				return false;
			}
			User::Current()->setUserName(m_NewUserName);
		}
		if (!this->commentChanged) User::Current()->setUserName(le_Comment->text());
		bool ret = User::Current()->submitChange();
		if (ret) {
			hideWarn();
			LOG_USER_OPERATION(ChangeUserName);
		}
		else {
			warn(tr("Submit change to database fail!"));
		}
		return ret;
	}
	else if (m_mode == Admin) {
		if (!this->userNameChanged && !this->roleChanged) return true;
		User user;
		if (!User::getUser(m_UserID, user)) return true;
		if (this->userNameChanged) {
			if (m_NewUserName.isEmpty()) {
				warn(tr("User Name can't be empty!"));
				return false;
			}
			user.setUserName(m_NewUserName);
		}
		if (this->roleChanged) user.setRoleID(m_RoleID);
		if (!this->commentChanged) user.setComment(le_Comment->text());
		bool ret = user.submitChange();
		if (ret) {
			LOG_USER_OPERATION(AdminChangeAcountInformation);
		}
		return ret;
	}
	else {
		//add new
		User user;
		if (le_UserCode->text().isEmpty()) {
			warn(tr("User ID can't be empty!"));
			return false;
		}
		if (le_UserName->text().isEmpty()) {
			warn(tr("User Name can't be empty!"));
			return false;
		}
		if (le_Pwd->text().isEmpty()) {
			warn(tr("Password can't be empty!"));
			return false;
		}
		if (!refmodel) {
			warn(tr("Inner error ,unset data model!"));
			return false;
		}
		if (User::existsUser(le_UserCode->text())) {
			warn(tr("User Id exists!"));
			return false;
		}
		hideWarn();
		user.setUserName(le_UserName->text());
		user.setPassword(User::getEncryptedPassword(le_Pwd->text()));
		user.setRoleID(m_RoleID);
		user.setComment(le_Comment->text());
		//        User::insertUser(le_UserCode->text(),user);

		refmodel->insertRow(0);
		refmodel->setData(refmodel->index(0, 0), QUuid::createUuid().toString());
		refmodel->setData(refmodel->index(0, 1), le_UserCode->text());
#define USER_READONLY_PROPERTY(name) name,
#define USER_PROPERTY(name)\
            USER_READONLY_PROPERTY(name)

		enum user_index {
			USER_PROPERTIES_MACRO()
		};
#undef USER_READONLY_PROPERTY
#undef USER_PROPERTY

#define USER_READONLY_PROPERTY(name)
#define USER_PROPERTY(name)\
            USER_READONLY_PROPERTY(name)\
            refmodel->setData(refmodel->index(0, name),user.get##name());
		USER_PROPERTIES_MACRO()
#undef USER_READONLY_PROPERTY
#undef USER_PROPERTY

			if (refmodel->submit()) {
				hideWarn();
				return true;
			}
			else {
				warn(tr("Submit to data base fail!"));
				return false;
			}
	}
	return true;
}

void AccountFormDialog::setAccountInformation(const QMap<QString, QVariant>& values) {
	le_UserCode->setText(values["UserCode"].toString());
	le_UserName->setText(values["UserName"].toString());
	le_Comment->setText(values["Comment"].toString());
	m_UserID = values["UserID"].toString();
	m_UserPwd = values["Password"].toString();
}

void AccountFormDialog::warn(QString msg) {
	lbl_error->setText(msg);
	lbl_error->setVisible(true);
}

void AccountFormDialog::hideWarn() {
	this->lbl_error->setVisible(false);
}
