#include "FormTxDufaultProfile.h"
#include "ui_FormTxDufaultProfile.h"

#include <QScroller>

#include "Globals.h"
#include "ConfigManager.h"
#include "LanguageManager.h"
#include "GeneralInterface.h"

FormTxDufaultProfile::FormTxDufaultProfile(BaseWidget *parent)
    : BaseWidget(parent)
    , ui(new Ui::FormTxDufaultProfile)
{
    ui->setupUi(this);

    initWidget();
    initConnect();
}

FormTxDufaultProfile::~FormTxDufaultProfile()
{
    delete ui;
}

bool FormTxDufaultProfile::returnParent()
{
    return updateData();
}

void FormTxDufaultProfile::initWidget()
{
    initComboBox();
    initTableWidget();
    initListWidget();

    m_limit_dialog.reset(new DialogLimitEdit());
    m_limit_dialog->setParent(this);
    m_limit_dialog->setWindowFlags(Qt::Window | Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint);
    m_limit_dialog->setWindowModality(Qt::WindowModal);

    m_weekday_dialog.reset(new DialogWeekDayDetail());
    m_weekday_dialog->setParent(this);
    m_weekday_dialog->setWindowFlags(Qt::Window | Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint);
    m_weekday_dialog->setWindowModality(Qt::WindowModal);
}

void FormTxDufaultProfile::initConnect()
{
    connect(LanguageManager::instance(), &LanguageManager::languageChanged,     this, [this]() {
        ui->retranslateUi(this);
    });
    connect(GLOBALS, &Globals::ocppConfigKeyValueChanged, this, [this](const CONFIG_KEY_INFO& info) {
        if (info.SmartChargingProfile.ChargeProfileMaxStackLevel != ui->stackLevel->count()) {
            initStackLevelComboBox();
            ui->stackLevel->setCurrentText(QString::number(m_profile_info.stackLevel));
        }
    });
    connect(ui->chargingProfileKind,    &CustomComboBox::currentIndexChanged,   this, [this](const int& index) {
        switch (index) {
        case ChargingProfiles::Kind::ABSOLUTE_ID:
        case ChargingProfiles::Kind::RELATIVE_ID:
            ui->recurrencyKind->setCurrentIndex(ChargingProfiles::RecurrencyKind::NO_RECURRING_ID);
            ui->recurrencyKind->setEnabled(false);
            break;
        case ChargingProfiles::Kind::RECURRING_ID:
            ui->recurrencyKind->setEnabled(true);
            break;
        default:
            break;
        }
    });

    connect(ui->recurrencyKind,         &CustomComboBox::currentIndexChanged,   this, [this](const int& index) {
        switch (index) {
        case ChargingProfiles::RecurrencyKind::NO_RECURRING_ID:
            ui->stackedWidget->setCurrentWidget(ui->no_recyrrency);
            break;
        case ChargingProfiles::RecurrencyKind::DAILY_ID:
            ui->stackedWidget->setCurrentWidget(ui->daily);
            refreshDailyData();
            break;
        case ChargingProfiles::RecurrencyKind::WEEKLY_ID:
            ui->stackedWidget->setCurrentWidget(ui->weekly);
            refreshWeeklyData();
            break;
        default:
            break;
        }
    });

    connect(ui->chargingRateUnit,       &CustomComboBox::currentIndexChanged,   this, [this](const int& index) {
        switch (index) {
        case ChargingProfiles::UnitType::AMPERE_ID:
            ui->unit->setText(tr("A"));
            break;
        case ChargingProfiles::UnitType::WATT_ID:
            ui->unit->setText(tr("KW"));
            break;
        default:
            break;
        }
    });

    connect(ui->add_limit,              &QPushButton::clicked,                  this, &FormTxDufaultProfile::addBtnClicked);
    connect(ui->delete_limit,           &QPushButton::clicked,                  this, &FormTxDufaultProfile::deleteBtnClicked);

    connect(ui->dailyTablewidget,       &QTableWidget::itemDoubleClicked,       this, &FormTxDufaultProfile::dialyTableWidgetClicked);
    connect(ui->weeklyListwidget,       &QListWidget::itemDoubleClicked,        this, &FormTxDufaultProfile::weekdayTableWidgetDoubleClicked);

    connect(m_weekday_dialog.data(),    &DialogWeekDayDetail::valueChanged,     this, [this]() {
        setIsModify(true);
    });
}

void FormTxDufaultProfile::initComboBox()
{
    QStringList kind_list;
    kind_list << ChargingProfiles::Kind::ABSOLUTE
              << ChargingProfiles::Kind::RELATIVE
              << ChargingProfiles::Kind::RECURRING;
    ui->chargingProfileKind->addItems(kind_list);

    QStringList recurrencyKindList;
    recurrencyKindList << ChargingProfiles::RecurrencyKind::NO_RECURRING
                       << ChargingProfiles::RecurrencyKind::DAILY
                       << ChargingProfiles::RecurrencyKind::WEEKLY;
    ui->recurrencyKind->addItems(recurrencyKindList);

    QStringList rateUnit;
    rateUnit << ChargingProfiles::UnitType::WATT
             << ChargingProfiles::UnitType::AMPERE;
    ui->chargingRateUnit->addItems(rateUnit);

    initStackLevelComboBox();
}

void FormTxDufaultProfile::initStackLevelComboBox()
{
    ui->stackLevel->clear();
    auto maxStackLevel = ConfigManager::instance()->cfg_key().SmartChargingProfile.ChargeProfileMaxStackLevel;
    QStringList stackLevelList;
    for (int index = 0; index <= maxStackLevel; index ++) {
        stackLevelList.append(QString::number(index));
    }
    ui->stackLevel->addItems(stackLevelList);
}

void FormTxDufaultProfile::initTableWidget()
{
    // ui->dailyTablewidget->horizontalHeader()->hide();
    ui->dailyTablewidget->verticalHeader()->hide();

    ui->dailyTablewidget->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);

    ui->dailyTablewidget->setEditTriggers(QAbstractItemView::NoEditTriggers);
    ui->dailyTablewidget->setSelectionBehavior(QAbstractItemView::SelectRows);
    ui->dailyTablewidget->setSelectionMode(QAbstractItemView::SingleSelection);

    QScroller::grabGesture(ui->dailyTablewidget,              QScroller::TouchGesture);
    QScroller::grabGesture(ui->dailyTablewidget->viewport(),  QScroller::LeftMouseButtonGesture);
}

void FormTxDufaultProfile::initListWidget()
{

}

void FormTxDufaultProfile::refreshData()
{
    refreshGeneralData();
}

void FormTxDufaultProfile::refreshGeneralData()
{
    if (m_profile_info.chargingProfilePurpose != ui->chargingProfilePurpose->text()) return;
    ui->connectorID->setText(QString::number(m_profile_info.connectorId));
    ui->chargingProfileKind->setCurrentText(m_profile_info.chargingProfileKind);
    ui->recurrencyKind->setCurrentText(m_profile_info.recurrencyKind);
    ui->startTime->setDateTime(QDateTime::fromString(m_profile_info.chargingSchedule.startTime, Qt::ISODate));
    ui->stackLevel->setCurrentText(QString::number(m_profile_info.stackLevel));
}

void FormTxDufaultProfile::refreshDailyData()
{
    ui->dailyTablewidget->clearContents();
    ui->dailyTablewidget->setRowCount(0);
    foreach (const auto& duration_info, m_profile_info.chargingSchedule.chargingSchedulePeriod) {
        QString limitStr = "";
        if (m_profile_info.chargingSchedule.chargingRateUnit == ChargingProfiles::UnitType::AMPERE) {
            limitStr = QString("%1 A").arg(QString::number(duration_info.limit / 1000.0, 'f', 2));
        } else if (m_profile_info.chargingSchedule.chargingRateUnit == ChargingProfiles::UnitType::WATT) {
            limitStr = QString("%1 KW").arg(QString::number(duration_info.limit / 1000.0, 'f', 2));
        }
        QString startPeriod = GeneralInterface::getCurrentDate(duration_info.startPeriod);
        appendRowTableWidget(startPeriod,
                             m_profile_info.chargingSchedule.chargingRateUnit,
                             limitStr);
    }
}

void FormTxDufaultProfile::refreshWeeklyData()
{

}

void FormTxDufaultProfile::refreshDefaultData()
{

}

void FormTxDufaultProfile::appendRowTableWidget(const QString &startTime, const QString &limitType, const QString &limit)
{
    auto row = ui->dailyTablewidget->rowCount();
    ui->dailyTablewidget->insertRow(row);

    auto startTimeItem = new QTableWidgetItem(startTime);
    startTimeItem->setTextAlignment(Qt::AlignCenter);
    ui->dailyTablewidget->setItem(row, 0, startTimeItem);

    auto limitTypeItem = new QTableWidgetItem(limitType);
    limitTypeItem->setTextAlignment(Qt::AlignCenter);
    ui->dailyTablewidget->setItem(row, 1, limitTypeItem);

    auto limitItem = new QTableWidgetItem(limit);
    limitItem->setTextAlignment(Qt::AlignCenter);
    ui->dailyTablewidget->setItem(row, 2, limitItem);

    ui->dailyTablewidget->setRowHeight(row, 60);
}

bool FormTxDufaultProfile::updateData()
{
    CHARGING_PROFILES profile_infos = ConfigManager::instance()->charging_profiles();
    for(int index = 0; index < profile_infos.chargingProfiles.size(); index ++) {
        if (profile_infos.chargingProfiles[index].chargingProfilePurpose == m_profile_info.chargingProfilePurpose &&
            profile_infos.chargingProfiles[index].chargingProfileId == m_profile_info.chargingProfileId) {
            profile_infos.chargingProfiles[index] = m_profile_info;
        }
    }

    return ConfigManager::instance()->saveConfig(CHARGING_PROFILE, QVariant::fromValue(profile_infos));
}

QList<charging_schedule_period_info_t> FormTxDufaultProfile::getDayOfWeekLimitList(const QList<charging_schedule_period_info_t> &dataList, const QString &startTime, const int &curDay)
{
    QList<charging_schedule_period_info_t> result;
    foreach (const auto& data, std::as_const(dataList)) {
        if (isDayOfWeek(startTime, curDay, data.startPeriod)) {
            result.append(data);
        }
    }

    return result;
}

bool FormTxDufaultProfile::isDayOfWeek(const QString &startTime, const int &curDay, const int &seconds)
{
    // 1. 解析开始时间
    QDateTime startDt = QDateTime::fromString(startTime, Qt::ISODate);
    startDt.setTimeSpec(Qt::UTC); // 若有Z，确保为UTC

    // 2. 计算目标时间
    QDateTime targetDt = startDt.addSecs(seconds);

    // 3. 判断目标时间是否为指定周几
    return targetDt.date().dayOfWeek() == curDay;
}

void FormTxDufaultProfile::updateWeekPeriodList(QList<charging_schedule_period_info_t> &dataList, const QList<charging_schedule_period_info_t> &newDataList, const QString &startTime, const int &curDay)
{
    for(int row = dataList.size() - 1; row >= 0; --row) {
        if (isDayOfWeek(startTime, curDay, dataList[row].startPeriod)) {
            dataList.removeAt(row);
        }
    }

    dataList.append(newDataList);

    GeneralInterface::sortByStartPeriod(dataList);
}

int FormTxDufaultProfile::indexOfWeekPeriodList(const QList<charging_schedule_period_info_t> &dataList, const charging_schedule_period_info_t &data)
{
    for (int index = 0; index < dataList.size(); index ++) {
        if (dataList[index].startPeriod == data.startPeriod) {
            return index;
        }
    }

    return -1;
}

void FormTxDufaultProfile::dialyTableWidgetClicked(QTableWidgetItem *item)
{
    Limit limit_info;
    limit_info.startPeriod      = m_profile_info.chargingSchedule.chargingSchedulePeriod[item->row()].startPeriod;
    limit_info.unit             = m_profile_info.chargingSchedule.chargingRateUnit;
    limit_info.limit            = m_profile_info.chargingSchedule.chargingSchedulePeriod[item->row()].limit;

    m_limit_dialog->setLimit_info(limit_info);
    auto ret = m_limit_dialog->exec();
    if (ret == QDialog::Accepted) {
        auto result = m_limit_dialog->limit_info();
        m_profile_info.chargingSchedule.chargingSchedulePeriod[item->row()].startPeriod          = result.startPeriod;
        m_profile_info.chargingSchedule.chargingRateUnit                                         = result.unit;
        m_profile_info.chargingSchedule.chargingSchedulePeriod[item->row()].limit                = result.limit;

        m_profile_info.chargingSchedule.startTime = ui->startTime->dateTime().toString(Qt::ISODate);

        refreshDailyData();
        setIsModify(true);
    }
}

void FormTxDufaultProfile::weekdayTableWidgetDoubleClicked(QListWidgetItem *item)
{
    GeneralInfo generalInfo;
    generalInfo.startTime           = m_profile_info.chargingSchedule.startTime;
    generalInfo.curDay              = ui->weeklyListwidget->row(item) + 1;
    generalInfo.chargingRateUnit    = m_profile_info.chargingSchedule.chargingRateUnit;
    m_weekday_dialog->setGeneralInfo(generalInfo);

    auto dayOfWeekList = getDayOfWeekLimitList(m_profile_info.chargingSchedule.chargingSchedulePeriod, generalInfo.startTime, generalInfo.curDay);
    m_weekday_dialog->setInfo_list(dayOfWeekList);
    auto ret = m_weekday_dialog->exec();
    if (ret == QDialog::Accepted) {
        auto limitList = m_weekday_dialog->info_list();
        updateWeekPeriodList(m_profile_info.chargingSchedule.chargingSchedulePeriod, limitList, generalInfo.startTime, generalInfo.curDay);
        setIsModify(true);
    }
}

void FormTxDufaultProfile::addBtnClicked()
{
    m_limit_dialog->clear();
    auto ret = m_limit_dialog->exec();
    if (ret == QDialog::Accepted) {
        auto result = m_limit_dialog->limit_info();

        charging_schedule_period_info_t info;
        info.startPeriod = result.startPeriod;
        info.limit = result.limit;
        m_profile_info.chargingSchedule.chargingSchedulePeriod.append(info);

        GeneralInterface::sortByStartPeriod(m_profile_info.chargingSchedule.chargingSchedulePeriod);

        refreshDailyData();
        setIsModify(true);
    }
}

void FormTxDufaultProfile::deleteBtnClicked()
{
    auto row = ui->dailyTablewidget->currentRow();
    if (row < 0) return;
    if (row > m_profile_info.chargingSchedule.chargingSchedulePeriod.size()) return;
    m_profile_info.chargingSchedule.chargingSchedulePeriod.removeAt(row);

    refreshDailyData();
    setIsModify(true);
}

void FormTxDufaultProfile::showEvent(QShowEvent *event)
{
    setIsModify(false);
    refreshData();
    BaseWidget::showEvent(event);
}

charging_profiles_detail_info_t FormTxDufaultProfile::profile_info() const
{
    return m_profile_info;
}

void FormTxDufaultProfile::setProfile_info(charging_profiles_detail_info_t newProfile_info)
{
    m_profile_info = newProfile_info;
}
