//
// Created by uos on 2022/5/16.
//

#include "BackupFileManagerDialog.h"
#include "utils/Utils.h"
#include "common/BaseItemDelegate.h"
#include <QVBoxLayout>
#include <DLabel>
#include <QPushButton>
#include <DTitlebar>
#include <DFontSizeManager>
#include <DBackgroundGroup>
#include <QHeaderView>
#include <QDateTime>
#include <QScreen>
#include <DLineEdit>
#include <DDialog>
#include <QDebug>

const int TABLE_COL_NO = 0;             //table表：序号
const int TABLE_COL_NAME = 1;           //table表：备份文件名
const int TABLE_COL_TIME = 2;           //table表：时间
const int TABLE_COL_BACKUP_FILE = 3;    //table表：备份文件
const int TABLE_COL_USER = 4;           //table表：用户
const int TABLE_COL_STATE = 5;         //table表：备份文件状态
const int TABLE_COL_REMARK = 6;          //table表：备注
const int TABLE_COL_ACTION = 7;         //table表：操作
const int TABLE_COL_OPT_ID = 8;         //table表：操作ID

const static int systemBackupIndex = 0;
const static int dataBackupIndex = 1;
const static int ghostBackupIndex = 2;
bool DeleteWidget::m_isRemoving = false;

static void deleteBackupInfo(BackupInfoList &backupList, const QString &operateId)
{
    if (backupList.isEmpty()) {
        return;
    }

    backupList.erase(std::remove_if(backupList.begin(), backupList.end(),
                                    [&] (const BackupInfo &b) -> bool {
                                        return b.operateID == operateId;
                                    }),
                     backupList.end());
}

DeleteWidget::DeleteWidget(QWidget *parent)
    : QWidget(parent)
{
    QHBoxLayout *layout = new QHBoxLayout;
    layout->setAlignment(Qt::AlignLeft);
    setLayout(layout);
    m_deleteBtn = new DPushButton;
    m_deleteBtn->setStyleSheet("QPushButton {"
                                 "color: #0081FF;"
                                 "border: none;"
                                 "background-color: transparent;"
                                 "image:url(:/resources/icons/delete.svg);"
                                 "}");
    //m_deleteBtn->setIcon(QIcon::fromTheme(":/resources/icons/delete.svg"));
    layout->addWidget(m_deleteBtn);
    m_spinner = new DSpinner;
    m_spinner->setFixedSize(24, 24);
    m_spinner->setVisible(false);
    layout->addWidget(m_spinner);
    connect(m_deleteBtn, &QPushButton::clicked, this, &DeleteWidget::onDelete);
}

void DeleteWidget::setBackupInfo(const BackupInfo &backupInfo)
{
    m_backupInfo = backupInfo;
}

void DeleteWidget::checkAdminAuthority(AuthorityType type)
{
    if (nullptr == m_adminAuthUtils) {
        m_adminAuthUtils = new AuthorityUtils();
        connect(m_adminAuthUtils, &AuthorityUtils::notifyAdminAuthority, this, &DeleteWidget::doAdminAuthorityTask);
    }
    m_adminAuthUtils->authorization(type);
}

void DeleteWidget::checkCommonAuthority(AuthorityType type)
{
    if (nullptr == m_commonAuthUtils) {
        m_commonAuthUtils = new AuthorityUtils();
        connect(m_commonAuthUtils, &AuthorityUtils::notifyCommonUserAuthority, this, &DeleteWidget::doCommonAuthorityTask);
    }

    m_commonAuthUtils->checkCommonUserAuthentication(type);
}

void DeleteWidget::doAdminAuthorityTask(bool result, int type)
{
    if (result) {
        AuthorityType authType = static_cast<AuthorityType>(type);
        if (AuthorityType::DeleteSystemBackupV20 == authType) {
            return;
        }
        if (AuthorityType::DeleteImmutableSystemBackup == authType || AuthorityType::DeleteSystemBackup == authType) {
            m_isRemoving = true;

            // 先修改状态，后发送信号，避免删除失败导致状态无法更正
            m_deleteBtn->setVisible(false);
            m_spinner->setVisible(true);
            m_spinner->start();

            Q_EMIT deleteBackupInfo(m_backupInfo);
            return;
        }
    }
}

void DeleteWidget::doCommonAuthorityTask(bool result, int type)
{
    if (result) {
        AuthorityType authType = static_cast<AuthorityType>(type);
        if (AuthorityType::DeleteDataBackup == authType) {
            m_isRemoving = true;

            // 先修改状态，后发送信号，避免删除失败导致状态无法更正
            m_deleteBtn->setVisible(false);
            m_spinner->setVisible(true);
            m_spinner->start();

            Q_EMIT deleteBackupInfo(m_backupInfo);
        }
    }
}

void DeleteWidget::onDelete()
{
    if (m_isRemoving) {
        return;
    }

    OperateType opType = static_cast<OperateType>(m_backupInfo.operateType);
    if (opType == OperateType::SystemBackup) {
        return this->checkAdminAuthority(AuthorityType::DeleteSystemBackup);
    } else if (opType == OperateType::ImmutableSystemBackup) {
        return this->checkAdminAuthority(AuthorityType::DeleteImmutableSystemBackup);
    } else if (opType == OperateType::UserDataBackup) {
        return this->checkCommonAuthority(AuthorityType::DeleteDataBackup);
    } else if (opType == OperateType::GhostBackup) {
        m_isRemoving = true;

        // 先修改状态，后发送信号，避免删除失败导致状态无法更正
        m_deleteBtn->setVisible(false);
        m_spinner->setVisible(true);
        m_spinner->start();

        Q_EMIT deleteBackupInfo(m_backupInfo);
    }
}

void DeleteWidget::setDeleteBtnVisible(bool visible)
{
    if (m_deleteBtn != nullptr) {
        m_deleteBtn->setVisible(visible);
    }
}

void DeleteWidget::stopSpinner()
{
    if (m_spinner != nullptr) {
        m_spinner->stop();
    }
}

void DeleteWidget::setSpinnerVisible(bool visible)
{
    if (m_spinner != nullptr) {
        m_spinner->setVisible(visible);
    }
}

BackupFileDelegate::BackupFileDelegate(QObject *parent)
    : BaseItemDelegate(parent)
{

}

QWidget * BackupFileDelegate::createEditor(QWidget *widget,
                                           const QStyleOptionViewItem &styleOptionViewItem,
                                           const QModelIndex &index) const
{
    //todo 支持编辑备注
//    if (index.column() == TABLE_COL_REMARK) {
//        return new DLineEdit(widget);
//    }
    return nullptr;
}

void BackupFileDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
{
    //todo 支持编辑备注
}

void BackupFileDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
{
    //todo 支持编辑备注
}

BackupFileManagerDialog::BackupFileManagerDialog(QWidget *parent) : DMainWindow(parent)
{
    this->setAccessibleName("BackupFileManagerDialog");
    m_isCommunity = Utils::isCommunity();

    // 主题变换
    m_guiHelper = Dtk::Gui::DGuiApplicationHelper::instance();
    connect(m_guiHelper, &Dtk::Gui::DGuiApplicationHelper::themeTypeChanged, this, &BackupFileManagerDialog::onThemeChange);
    // 初始化UI
    initUI();
    onThemeChange();
}

void BackupFileManagerDialog::initUI()
{
    auto titleBar = titlebar();
    setWindowFlags(windowFlags());// & ~Qt::WindowMinimizeButtonHint);
    titleBar->setMenuVisible(false);
    titleBar->setIcon(QIcon::fromTheme("uos-recovery"));
    auto contentLayout = new QVBoxLayout;
    contentLayout->setSpacing(10);
    contentLayout->setContentsMargins(10, 16, 10, 50);

    DLabel *label = new DLabel;
    label->setText(tr("Backup files"));
    label->setAccessibleName("BackupFileMgrDlg_BackupFiles");
    DFontSizeManager::instance()->bind(label, DFontSizeManager::T5);
    QFont font = label->font();
    font.setWeight(QFont::DemiBold);
    label->setFont(font);
    label->setAlignment(Qt::AlignLeft | Qt::AlignVCenter);
    QPalette titlePalette;
    titlePalette.setColor(QPalette::BrightText, QColor(qRgba(0,0,0,0.85)));
    label->setPalette(titlePalette);

    m_backupTypeCombox = new DComboBox;
    m_backupTypeCombox->addItem(tr("System backup"));
    m_backupTypeCombox->addItem(tr("Data backup"));
    if (!m_isCommunity) {
        m_backupTypeCombox->addItem(tr("System Clone"));
    }
    m_backupTypeCombox->setAccessibleName("BackupFileMgrDlg_TypeCombox");
    m_backupTypeCombox->setAccessibleDescription("BackupFileMgrDlg_TypeComboxDes");
    m_backupTypeCombox->setMinimumWidth(115);
    connect(m_backupTypeCombox, (void (QComboBox::*)(int)) &DComboBox::currentIndexChanged,
            this, (void (BackupFileManagerDialog::*)(int))&BackupFileManagerDialog::onBackupTypeComboxIndexChanged);
    QHBoxLayout *backupHBoxLayout = new QHBoxLayout;
    backupHBoxLayout->addWidget(label, 0, Qt::AlignLeft);
    backupHBoxLayout->addWidget(m_backupTypeCombox, 0, Qt::AlignRight);
    contentLayout->addLayout(backupHBoxLayout);

    QWidget *contentWidget = new QWidget;
    contentWidget->setObjectName("contentWidget");
    contentWidget->setAccessibleName("BackupFileMgrDlg_contentWidget");
    contentWidget->setLayout(contentLayout);

    auto mainLayout = new QHBoxLayout;
    auto mainWidget = new DBackgroundGroup();
    mainWidget->setObjectName("mainWidget");
    mainWidget->setAccessibleName("BackupFileMgrDlg_mainWidget");
    mainLayout->addWidget(contentWidget);
    setCentralWidget(mainWidget);
    centralWidget()->setLayout(mainLayout);

    m_tableView = new BaseTableView;
    m_tableView->setAccessibleName("BackupFileMgrDlg_tableView");
    m_model = new QStandardItemModel;
    m_tableView->setModel(m_model);
    auto itemDelegate = new BackupFileDelegate(this);
    m_tableView->setItemDelegate(itemDelegate);
    initTableView();
    contentLayout->addWidget(m_tableView);
    contentLayout->addStretch();

}

void BackupFileManagerDialog::initTableView()
{
    m_tableView->setFixedHeight(304);
    //m_tableView->setEditTriggers(QAbstractItemView::NoEditTriggers);
    m_tableView->setSortingEnabled(false);
    m_tableView->setFocusPolicy(Qt::NoFocus);
    m_tableView->setRowBackgroundDelta(10);

    //序号
    auto noItem = new QStandardItem(tr("No."));
    noItem->setTextAlignment(Qt::AlignVCenter);
    //备份文件名
    auto nameItem = new QStandardItem(tr("Name"));
    nameItem->setTextAlignment(Qt::AlignVCenter);

    // 备份文件
    auto backupFileItem = new QStandardItem(tr("Backup File"));
    backupFileItem->setTextAlignment(Qt::AlignVCenter);

    // 时间
    auto timeItem = new QStandardItem(tr("Time"));
    timeItem->setTextAlignment(Qt::AlignVCenter);

    // 用户
    auto userItem = new QStandardItem(tr("User"));
    userItem->setTextAlignment(Qt::AlignVCenter);
    //备份状态
    auto stateItem = new QStandardItem(tr("State"));
    stateItem->setTextAlignment(Qt::AlignVCenter);
    //备注
    auto remarkItem = new QStandardItem(tr("Note"));
    remarkItem->setTextAlignment(Qt::AlignVCenter);
    // 操作
    auto actionItem = new QStandardItem(tr("Action"));
    actionItem->setTextAlignment(Qt::AlignVCenter);
    //操作id
    auto optIdItem = new QStandardItem();
    optIdItem->setTextAlignment(Qt::AlignVCenter);

    m_model->setHorizontalHeaderItem(TABLE_COL_NO, noItem);
    m_model->setHorizontalHeaderItem(TABLE_COL_NAME, nameItem);
    m_model->setHorizontalHeaderItem(TABLE_COL_TIME, timeItem);
    m_model->setHorizontalHeaderItem(TABLE_COL_BACKUP_FILE, backupFileItem);
    m_model->setHorizontalHeaderItem(TABLE_COL_USER, userItem);
    m_model->setHorizontalHeaderItem(TABLE_COL_STATE, stateItem);
    m_model->setHorizontalHeaderItem(TABLE_COL_REMARK, remarkItem);
    m_model->setHorizontalHeaderItem(TABLE_COL_ACTION, actionItem);
    m_model->setHorizontalHeaderItem(TABLE_COL_OPT_ID, optIdItem);

    //m_tableView->header()->setSectionResizeMode(QHeaderView::ResizeToContents);
    m_tableView->setColumnWidth(TABLE_COL_NO, 20);
    m_tableView->setColumnWidth(TABLE_COL_OPT_ID, 5);
    m_tableView->setColumnWidth(TABLE_COL_TIME, 150);
    m_tableView->setColumnWidth(TABLE_COL_BACKUP_FILE, 180);
    m_tableView->setColumnWidth(TABLE_COL_USER, 130);
    m_tableView->setColumnWidth(TABLE_COL_REMARK, 160);
    m_tableView->setColumnWidth(TABLE_COL_ACTION, 30);

    //隐藏列
    m_tableView->hideColumn(TABLE_COL_NAME);
    m_tableView->hideColumn(TABLE_COL_STATE);
    m_tableView->hideColumn(TABLE_COL_OPT_ID);

    // 禁止拖动列宽
    QHeaderView * headerView = m_tableView->header();
    headerView->setSectionResizeMode(TABLE_COL_NO, QHeaderView::ResizeMode::Fixed);
    headerView->setSectionResizeMode(TABLE_COL_NAME, QHeaderView::ResizeMode::Fixed);
    headerView->setSectionResizeMode(TABLE_COL_TIME, QHeaderView::ResizeMode::Fixed);
    headerView->setSectionResizeMode(TABLE_COL_BACKUP_FILE, QHeaderView::ResizeMode::Fixed);
    headerView->setSectionResizeMode(TABLE_COL_USER, QHeaderView::ResizeMode::Fixed);
    headerView->setSectionResizeMode(TABLE_COL_STATE, QHeaderView::ResizeMode::Fixed);
    headerView->setSectionResizeMode(TABLE_COL_REMARK, QHeaderView::ResizeMode::Fixed);
    headerView->setSectionResizeMode(TABLE_COL_ACTION, QHeaderView::ResizeMode::Fixed);
}

void BackupFileManagerDialog::setData(BackupInfoList &backupInfos)
{
    m_model->removeRows(0, m_model->rowCount());
    m_allBackupInfo.clear();

    std::sort(backupInfos.begin(), backupInfos.end());
    auto iter = backupInfos.rbegin();
    int i = 1;
    for (; iter != backupInfos.rend(); ++iter, ++i) {
        m_allBackupInfo[iter->operateID] = *iter;
        int currentRow = m_model->rowCount();
        auto seqItem = new QStandardItem(QString("%1").arg(i));
        seqItem->setTextAlignment(Qt::AlignCenter);
        m_model->setItem(currentRow, TABLE_COL_NO, seqItem);
        m_model->setItem(currentRow, TABLE_COL_NAME, new QStandardItem(iter->operateID));
        QDateTime time = QDateTime::fromSecsSinceEpoch(iter->startTime); //时间戳-秒级
        if (OperateType::GhostBackup == static_cast<OperateType>(iter->operateType)) {
            time = QDateTime::fromMSecsSinceEpoch(iter->startTime);
        }
        QString startTime = time.toString("yyyy-MM-dd HH:mm:ss");
        auto timeItem = new QStandardItem(startTime);
        m_model->setItem(currentRow, TABLE_COL_TIME, timeItem);

        auto backupFileItem = new QStandardItem(iter->systemVersion);
//        if (iter->backupDeviceRemovable) {
//            destItem->setIcon(QIcon::fromTheme(":/resources/icons/drive-harddisk-usb.svg"));
//        } else {
//            destItem->setIcon(QIcon::fromTheme(":/resources/icons/drive-harddisk.svg"));
//        }

        m_model->setItem(currentRow, TABLE_COL_BACKUP_FILE, backupFileItem);
        m_model->setItem(currentRow, TABLE_COL_USER, new QStandardItem(iter->username));
        m_model->setItem(currentRow, TABLE_COL_STATE, new QStandardItem(QString("%1").arg(iter->status)));
        m_model->setItem(currentRow, TABLE_COL_REMARK, new QStandardItem(iter->remark));

        auto actionItem = new QStandardItem();
        actionItem->setAccessibleText(iter->operateID + "_deleteWidget");
        m_model->setItem(currentRow, TABLE_COL_ACTION, actionItem);
        auto deleteWidget = new DeleteWidget;
        deleteWidget->setBackupInfo(*iter);
        m_tableView->setIndexWidget(m_model->index(currentRow, TABLE_COL_ACTION), deleteWidget);
        connect(deleteWidget, &DeleteWidget::deleteBackupInfo, this, &BackupFileManagerDialog::notifyDeleteBackupInfo);
        //操作id
        m_model->setItem(currentRow, TABLE_COL_OPT_ID, new QStandardItem(iter->operateID));
    }
}

void BackupFileManagerDialog::showToCenter()
{
    onBackupTypeComboxIndexChanged(m_backupTypeCombox->currentIndex());
    auto screen = QGuiApplication::primaryScreen();
    auto rect = screen->geometry();
    if (rect.width() < MAIN_WINDOW_WIDTH || rect.height() < MAIN_WINDOW_HEIGHT) {
        QWidget::showMaximized();
    } else {
        setFixedSize(QSize(MAIN_WINDOW_WIDTH - 80, MAIN_WINDOW_HEIGHT - 80));
        move((rect.width() - width()) / 2, (rect.height() - height()) / 2);
        QWidget::show();
    }
}

void BackupFileManagerDialog::removeBackupInfo(const QString &operateId)
{
    m_allBackupInfo.remove(operateId);
    auto items = m_model->findItems(operateId, Qt::MatchExactly, TABLE_COL_OPT_ID);
    for (auto &item : items) {
        m_model->removeRow(m_model->indexFromItem(item).row());
        DeleteWidget::m_isRemoving = false;
    }

    int curIndex = m_backupTypeCombox->currentIndex();
    if (systemBackupIndex == curIndex) {
        deleteBackupInfo(m_allSystemBackupInfo, operateId);
    } else if (dataBackupIndex == curIndex) {
        deleteBackupInfo(m_allDataBackupInfo, operateId);
    } else if (ghostBackupIndex == curIndex) {
        deleteBackupInfo(m_allGhostBackupInfo, operateId);
    }
}

void BackupFileManagerDialog::onThemeChange()
{

}

void BackupFileManagerDialog::showErrorDlg(const QString &msg)
{
    DDialog dialog(this);
    dialog.setMessage(msg);
    dialog.setIcon(QIcon::fromTheme("dialog-warning"));
    dialog.setAccessibleName("BackupFileManagerDialog_ErrorDialog");
    QRect rect = geometry();
    dialog.move(rect.center());
    dialog.moveToCenter();
    dialog.exec();
}

void BackupFileManagerDialog::setDeleteWidgetStatus(bool deleteBtnVisible, bool spinnerVisible, const QString &operateId)
{
    auto items = m_model->findItems(operateId, Qt::MatchExactly, TABLE_COL_OPT_ID);
    for (auto &item : items) {
        int currentRow = m_model->indexFromItem(item).row();
        qInfo()<<Q_FUNC_INFO<<"currentRow = "<<currentRow<<", operateId = "<<operateId;
        QWidget *curWidget = m_tableView->indexWidget(m_model->index(currentRow, TABLE_COL_ACTION));
        DeleteWidget *curDeleteWidget = dynamic_cast<DeleteWidget *>(curWidget);
        if (curDeleteWidget != nullptr) {
            curDeleteWidget->stopSpinner();
            curDeleteWidget->setSpinnerVisible(spinnerVisible);
            curDeleteWidget->setDeleteBtnVisible(deleteBtnVisible);
        }
        DeleteWidget::m_isRemoving = false;
    }
}

void BackupFileManagerDialog::setSystemBackupInfoData(const BackupInfoList &backupInfos)
{
    m_allSystemBackupInfo = backupInfos;
}

void BackupFileManagerDialog::setDataBackupInfoData(const BackupInfoList &backupInfos)
{
    m_allDataBackupInfo = backupInfos;
}

void BackupFileManagerDialog::setGhostInfoData(const BackupInfoList &backupInfos)
{
    m_allGhostBackupInfo = backupInfos;
}

void BackupFileManagerDialog::onBackupTypeComboxIndexChanged(int index)
{
    QString curUserName = Utils::getUserName();
    bool isAdmin = Utils::isAdminUser(curUserName);
    if (systemBackupIndex == index) {
        if (isAdmin) {
            this->setData(m_allSystemBackupInfo);
        } else {
            BackupInfoList emptyList;
            this->setData(emptyList);
        }
    } else if (dataBackupIndex == index) {
        this->setData(m_allDataBackupInfo);
    } else if (ghostBackupIndex == index) {
        this->setData(m_allGhostBackupInfo);
    }
}

// void BackupFileManagerDialog::closeEvent(QCloseEvent *event)
// {
//     DMainWindow::closeEvent(event);
// //    this->close();
//     Q_EMIT closeMainWindow();
// }
