#include "mainwindow.h"
#include "./ui_mainwindow.h"
#include "alarmsservice.h"
#include "flowlayout.h"
#include "paginationbar.h"
#include "sensordialog.h"
#include "alarmwidget.h"
#include "journalservice.h"
#include "logwidget.h"
#include "qcustomplot.h"
#include "serverwidget.h"

#include <QComboBox>
#include <QDateTime>
#include <QGridLayout>
#include <QMessageBox>
#include <QResizeEvent>
#include <QScrollArea>
#include <QTimer>
#include <QDateTime>
#include <QTimeZone>

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    httpClient = new HttpClient(this);
    sensorService = new SensorService(httpClient, this);
    alarmsService = new AlarmsService(httpClient, this);
    journalService = new JournalService(httpClient, this);

    TranslateUpdate();
    SetupSensorTab();
    startRefreshTimer();
    SetupIncidentTab();
    SetupStatisticTab();
    SetupJournalTab();
    //------------------------------------------------------------------------------
    settings = sensorService->getSettings();
    ui->serialLineEdit->setText(settings.serial);
    ui->factoryLineEdit->setText(settings.factory);
    ui->exhuyantLineEdit->setText(settings.exhuyant);
    ui->fleetLineEdit->setText(settings.fleet);
    ui->sideLineEdit->setText(settings.side);
    ui->gosNumberLineEdit->setText(settings.gosNumber);
    ui->factoryNumberLineEdit->setText(settings.factoryNumber);
    ui->groupLineEdit->setText(settings.group);
    ui->adresLineEdit->setText(settings.adres);
    ui->userNameLineEdit->setText(settings.userName);
    ui->userPasswordLineEdit->setText(settings.userPassword);
    ui->argusSerialLineEdit->setText(settings.argusSerial);

    QLayoutItem *child;
    while ((child = ui->scrollAreaServersLayout->takeAt(0)) != nullptr) {
        if (child->widget()) {
            child->widget()->deleteLater();
        }
    }

    for (const auto &server : settings.servers) {
        QString domain = server.first;
        int port = server.second.toInt();

        ServerWidget *serverWidget = new ServerWidget(domain, port, this);

        connect(serverWidget, &ServerWidget::removeWidget, this, [this, serverWidget]() {
            serverWidget->deleteLater();
        });

        ui->scrollAreaServersLayout->addWidget(serverWidget);
    }

    connect(ui->tabWidget, &QTabWidget::currentChanged, this, [this](int index) {
        if (index == 4) {
            settings = sensorService->getSettings();
        }
    });
    connect(ui->serverButtonSettings, &QPushButton::clicked, this, &MainWindow::onServerButtonSettings);
    connect(ui->saveButtonSettings, &QPushButton::clicked, this, &MainWindow::onSaveButtonSettings);
    connect(ui->cancelButtonSettings, &QPushButton::clicked, this, &MainWindow::onCancelButtonSettings);
    connect(ui->importButtonSettings, &QPushButton::clicked, this, &MainWindow::onImportButtonSettings);
    connect(ui->exportButtonSettings, &QPushButton::clicked, this, &MainWindow::onExportButtonSettings);
}

void MainWindow::onServerButtonSettings() {
    ServerWidget *serverWidget = new ServerWidget("", 0000, this);

    connect(serverWidget, &ServerWidget::removeWidget, this, [this, serverWidget]() {
        serverWidget->deleteLater();
    });

    ui->scrollAreaServersLayout->addWidget(serverWidget);
}

void MainWindow::onSaveButtonSettings(){
    settings.serial = ui->serialLineEdit->text();
    settings.factory = ui->factoryLineEdit->text();
    settings.exhuyant = ui->exhuyantLineEdit->text();
    settings.fleet = ui->fleetLineEdit->text();
    settings.side = ui->sideLineEdit->text();
    settings.gosNumber = ui->gosNumberLineEdit->text();
    settings.factoryNumber = ui->factoryNumberLineEdit->text();
    settings.group = ui->groupLineEdit->text();
    settings.adres = ui->adresLineEdit->text();
    settings.userName = ui->userNameLineEdit->text();
    settings.userPassword = ui->userPasswordLineEdit->text();
    settings.argusSerial = ui->argusSerialLineEdit->text();
    settings.servers.clear();
    QList<QPair<QString, QString>> updatedServers;
    for (int i = 0; i < ui->scrollAreaServersLayout->count(); ++i) {
        if (auto *serverWidget = qobject_cast<ServerWidget*>(ui->scrollAreaServersLayout->itemAt(i)->widget())) {
            if (!serverWidget->deleted) {
                qDebug() << serverWidget->getDomain() << ' ' << serverWidget->deleted;
                updatedServers.append(qMakePair(serverWidget->getDomain(), serverWidget->getPort()));
            }
        }
    }

    settings.servers = updatedServers;
    sensorService->updateSettings(settings);
    onCancelButtonSettings();
}

void MainWindow::onCancelButtonSettings(){
    settings = sensorService->getSettings();
    ui->serialLineEdit->setText(settings.serial);
    ui->factoryLineEdit->setText(settings.factory);
    ui->exhuyantLineEdit->setText(settings.exhuyant);
    ui->fleetLineEdit->setText(settings.fleet);
    ui->sideLineEdit->setText(settings.side);
    ui->gosNumberLineEdit->setText(settings.gosNumber);
    ui->factoryNumberLineEdit->setText(settings.factoryNumber);
    ui->groupLineEdit->setText(settings.group);
    ui->adresLineEdit->setText(settings.adres);
    ui->userNameLineEdit->setText(settings.userName);
    ui->userPasswordLineEdit->setText(settings.userPassword);
    ui->argusSerialLineEdit->setText(settings.argusSerial);
    QLayoutItem *child;
    while ((child = ui->scrollAreaServersLayout->takeAt(0)) != nullptr) {
        if (child->widget()) {
            child->widget()->deleteLater();
        }
    }
    for (const auto &server : settings.servers) {
        QString domain = server.first;
        int port = server.second.toInt();

        ServerWidget *serverWidget = new ServerWidget(domain, port, this);

        connect(serverWidget, &ServerWidget::removeWidget, this, [this, serverWidget]() {
            serverWidget->deleteLater();
        });

        ui->scrollAreaServersLayout->addWidget(serverWidget);
    }
}

void MainWindow::onImportButtonSettings() {
    QString filePath = QFileDialog::getOpenFileName(
        this,
        "Открыть файл настроек",
        QDir::homePath(),
        "JSON файлы (*.json);;Все файлы (*)"
        );

    if (filePath.isEmpty()) {
        return;
    }

    QFile file(filePath);
    if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
        QMessageBox::critical(this, "Ошибка", "Не удалось открыть файл настроек.");
        return;
    }

    QByteArray fileData = file.readAll();
    file.close();

    QJsonParseError parseError;
    QJsonDocument jsonDoc = QJsonDocument::fromJson(fileData, &parseError);
    if (parseError.error != QJsonParseError::NoError) {
        QMessageBox::critical(this, "Ошибка", "Файл содержит некорректный JSON: " + parseError.errorString());
        return;
    }

    if (!jsonDoc.isObject()) {
        QMessageBox::critical(this, "Ошибка", "Файл настроек должен содержать JSON-объект.");
        return;
    }

    QJsonObject settingsJson = jsonDoc.object();

    QJsonObject response = httpClient->post(utils::API_URL + "/settings/deviceSettings", settingsJson);

    if (response.isEmpty()) {
        QMessageBox::critical(this, "Ошибка", "Не удалось отправить настройки на сервер.");
    } else {
        QMessageBox::information(this, "Успех", "Настройки успешно импортированы.");
    }
    onCancelButtonSettings();
}

void MainWindow::onExportButtonSettings(){
    QJsonObject responseJson = httpClient->get(utils::API_URL + "/settings/deviceSettings");
    if (responseJson.isEmpty()) {
        QMessageBox::warning(this, "Ошибка", "Не удалось получить настройки с сервера.");
        return;
    }
    QString filePath = QFileDialog::getSaveFileName(
        this,
        "Сохранить файл настроек",
        QDir::homePath() + "/settings.json",
        "JSON файлы (*.json);;Все файлы (*)"
        );

    // Если путь не выбран, выходим
    if (filePath.isEmpty()) {
        return;
    }

    // Конвертируем JSON в строку
    QJsonDocument jsonDoc(responseJson);
    QByteArray jsonData = jsonDoc.toJson(QJsonDocument::Indented);

    // Сохраняем JSON в файл
    QFile file(filePath);
    if (file.open(QIODevice::WriteOnly | QIODevice::Text)) {
        file.write(jsonData);
        file.close();
        QMessageBox::information(this, "Успех", "Настройки успешно сохранены в файл.");
    } else {
        QMessageBox::critical(this, "Ошибка", "Не удалось сохранить настройки в файл.");
    }
}

void MainWindow::SetupStatisticTab() {
    statisticType = 0;

    ui->startSelectStatistic->setDisplayFormat("dd/MM/yyyy HH:mm");
    ui->endSelectStatistic->setDisplayFormat("dd/MM/yyyy HH:mm");
    updateComboboxStatistic();

    realTimeChartTimer = new QTimer(this);
    statisticChart = new QCustomPlot(this);
    statisticChart->setFixedSize(1210, 650);
    statisticChart->addGraph();

    QPen pen;
    pen.setColor(QColor(19, 58, 97));
    pen.setWidth(2);
    statisticChart->graph(0)->setPen(pen);

    QSharedPointer<QCPAxisTickerDateTime> dateTimeTicker(new QCPAxisTickerDateTime);
    dateTimeTicker->setDateTimeFormat("HH:mm:ss dd.MM.yyyy");
    statisticChart->xAxis->setTicker(dateTimeTicker);

    statisticChart->axisRect()->setupFullAxesBox();
    statisticChart->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom);

    ui->chartNButtonsLayout->addWidget(statisticChart);
    statisticChart->hide();

    connect(realTimeChartTimer, &QTimer::timeout, this, &MainWindow::updateRealTimeChart);

    connect(ui->sensorSelectStatistic, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &MainWindow::onSensorSelectStatisticChanged);
    connect(ui->realTimeButtonStatistic, &QPushButton::clicked, this, &MainWindow::onRealTimeStatisticClicked);
    connect(ui->archiveButtonStatistic, &QPushButton::clicked, this, &MainWindow::onArchiveStatisticClicked);
    connect(ui->showStatisticButton, &QPushButton::clicked, this, &MainWindow::onShowStatisticClicked);
}

void MainWindow::ondialogClosedFromWidget(QString groupWithSensor, QDateTime start, QDateTime end) {
    ui->tabWidget->setCurrentIndex(2);
    ui->sensorSelectStatistic->setCurrentIndex(groupWithSensorToIndex[groupWithSensor]);
    ui->startSelectStatistic->setDateTime(start);
    ui->endSelectStatistic->setDateTime(end);
    onArchiveStatisticClicked();
    onShowStatisticClicked();
}

void MainWindow::onSensorSelectStatisticChanged(int index) {
    if(statisticType) {
        onRealTimeStatisticClicked();
    }
}

void MainWindow::updateRealTimeChart() {
    if (!statisticChart) return;
    qint64 endTime = QDateTime::currentSecsSinceEpoch();
    qint64 startTime = endTime - 5;

    PlotData newData = sensorService->getDeviceSensorData(
        groupWithSensor[ui->sensorSelectStatistic->currentIndex()], startTime, endTime);

    if (!newData.X.isEmpty() && !newData.Y.isEmpty()) {

        for(size_t i = 0; i < newData.X.size(); ++i) {
            statisticChart->graph(0)->addData(newData.X[i], newData.Y[i]);
        }

        statisticChart->replot();
    }
}

void MainWindow::onRealTimeStatisticClicked() {
    statisticType = 1;
    ui->startSelectStatistic->hide();
    ui->endSelectStatistic->hide();
    ui->showStatisticButton->hide();
    ui->label_16->hide();
    ui->label_14->hide();

    if (statisticType) {
        ui->realTimeButtonStatistic->setStyleSheet(R"(
            QPushButton {
                border-style: solid;
                border-color: #d5cb7a;
                border-width: 2px;
                background-color: #d5cb7a;
                color: #13385F;
                font-family: Inter;
                font-size: 22px;
                font-weight: 500;
                line-height: 26.63px;
                text-align: center;
                border-top-left-radius: 5px;
                border-bottom-left-radius: 5px;
            }
        )");
        ui->archiveButtonStatistic->setStyleSheet(R"(
            QPushButton {
                border-style: solid;
                border-color: #d5cb7a;
                border-width: 2px;
                color: #13385F;
                font-family: Inter;
                font-size: 22px;
                font-weight: 500;
                line-height: 26.63px;
                text-align: center;
                border-top-right-radius: 5px;
                border-bottom-right-radius: 5px;
            }
        )");
    }



    ui->pseudoChart->hide();
    statisticChart->show();


    qint64 currentTime = QDateTime::currentSecsSinceEpoch();
    qint64 initialStartTime = 1;

    PlotData initialData = sensorService->getDeviceSensorData(
        groupWithSensor[ui->sensorSelectStatistic->currentIndex()], initialStartTime, currentTime);

    if (!initialData.X.isEmpty() && !initialData.Y.isEmpty()) {
        statisticChart->graph(0)->setData(initialData.X, initialData.Y);

        statisticChart->xAxis->setRange(initialData.X.last() - 600, initialData.X.last());
        statisticChart->yAxis->setRange(*std::min_element(initialData.Y.begin(), initialData.Y.end()) - 10,
                                    *std::max_element(initialData.Y.begin(), initialData.Y.end()) + 10);

        statisticChart->replot();
    }

    realTimeChartTimer->start(5000);
}

void MainWindow::onArchiveStatisticClicked() {
    if (realTimeChartTimer && realTimeChartTimer->isActive()) {
        realTimeChartTimer->stop();
    }
    statisticType = 0;
    statisticChart->hide();
    ui->pseudoChart->show();
    ui->startSelectStatistic->show();
    ui->endSelectStatistic->show();
    ui->showStatisticButton->show();
    ui->label_16->show();
    ui->label_14->show();
    if(!statisticType) {
        ui->realTimeButtonStatistic->setStyleSheet(R"(
            QPushButton {
                border-style: solid;
                border-color: #d5cb7a;
                border-width: 2px;
                color: #13385F;
                font-family: Inter;
                font-size: 22px;
                font-weight: 500;
                line-height: 26.63px;
                text-align: center;
                border-top-left-radius: 5px;
                border-bottom-left-radius: 5px;
            }
        )");
        ui->archiveButtonStatistic->setStyleSheet(R"(
            QPushButton {
                border-style: solid;
                border-color: #d5cb7a;
                border-width: 2px;
                background-color: #d5cb7a;
                color: #13385F;
                font-family: Inter;
                font-size: 22px;
                font-weight: 500;
                line-height: 26.63px;
                text-align: center;
                border-top-right-radius: 5px;
                border-bottom-right-radius: 5px;
            }
        )");
    }
}

void MainWindow::onShowStatisticClicked() {
    qDebug() << "1";
    ui->pseudoChart->hide();
    qDebug() << "2";
    if (!statisticChart) {
        qDebug() << "statisticChart is nullptr!";
        return;
    }
    statisticChart->show();
    qDebug() << "3";

    qint64 start = ui->startSelectStatistic->dateTime().toSecsSinceEpoch();
    if(!start) {
        start = 1;
    }
    qint64 end = ui->endSelectStatistic->dateTime().toSecsSinceEpoch();
    if(!end) {
        end = QDateTime::currentMSecsSinceEpoch();
    }
    PlotData data = sensorService->getDeviceSensorData(groupWithSensor[ui->sensorSelectStatistic->currentIndex()], start, end);

    qDebug() << "3";
    statisticChart->graph(0)->setData(data.X, data.Y);

    statisticChart->yAxis->setRange(*std::min_element(data.Y.begin(), data.Y.end()) - 10,
                                *std::max_element(data.Y.begin(), data.Y.end()) + 10);


    statisticChart->graph(0)->rescaleAxes();
    statisticChart->replot();
}

void MainWindow::updateComboboxStatistic() {
    ui->sensorSelectStatistic->clear();
    groupWithSensor.clear();

    sensorGroupTree tree = sensorService->getSensorGroupsTree();

    QStringList groups = tree.groupToLocalGroup.keys();

    std::sort(groups.begin(), groups.end(), [&tree](const QString &a, const QString &b) {
        return tree.groupToLocalGroup[a] < tree.groupToLocalGroup[b];
    });

    int index = 0;
    for (const QString &group : groups) {
        const QString &localizedGroupName = tree.groupToLocalGroup[group];

        if (tree.groupToSensorWithLocal.contains(group)) {
            const QMap<QString, QString> &sensors = tree.groupToSensorWithLocal[group];

            for (auto it = sensors.begin(); it != sensors.end(); ++it) {
                const QString &sensorId = it.key();
                const QString &sensorName = it.value();

                QString itemData = group + '/' + sensorId;

                groupWithSensorToIndex[itemData] = index;
                groupWithSensor.append(itemData);
                ui->sensorSelectStatistic->addItem(localizedGroupName + '/' + sensorName, QVariant::fromValue(itemData));
                index++;
            }
        }
    }
}


void MainWindow::SetupJournalTab() {
    loadSensorsTree(ui->treeJournal);

    connect(ui->searchJournal,
            &QLineEdit::textChanged,
            this,
            &MainWindow::onSearchJournalTextChanged);

    ui->timeIntervalJournal->addItems(
        {"За всё время", "За сегодня", "За вчера", "За последние 7 дней"});
    ui->statusJournal->addItems(
        {"Все статусы", "Отладка", "Информация", "Предупреждение", "Ошибка", "Экстренно"});
    ui->sortJournal->addItems({"По времени", "По критичности"});

    journalSettings = getJournalDataSettings();

    int amount = journalService->getLogsAmount(journalSettings->groupsWithSensors, journalSettings->status,
                                               journalSettings->start_time, journalSettings->end_time);

    paginationBarJournal = new PaginationBar((amount + 24 - 1)/ 24);
    ui->paginationBarJournalLayout->addStretch();
    ui->paginationBarJournalLayout->addWidget(paginationBarJournal);
    ui->paginationBarJournalLayout->addStretch();

    QList<LogsR> arr = journalService->getLogs(journalSettings->groupsWithSensors, journalSettings->status,
                                               journalSettings->cmp, journalSettings->start_time,
                                               journalSettings->end_time, 1, 24);

    for(int i = 0; i < arr.size(); ++i) {
        LogWidget *logWidget = new LogWidget(translate, arr[i].getTime(), arr[i].getMessage(),
                                             arr[i].getSensorId(), arr[i].getSensorGroup(),
                                             arr[i].getThreatLevel(), ui->scrollWidgetJournal);
        logWidget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
        ui->scrollLayoutJournal->addWidget(logWidget);
    }
    if (arr.size() < 24) {
        QSpacerItem *spacer = new QSpacerItem(0, 0, QSizePolicy::Minimum, QSizePolicy::Expanding);
        ui->scrollLayoutJournal->addSpacerItem(spacer);
    }

    connect(ui->searchLogs, &QPushButton::clicked, this, &MainWindow::onSearchJournalClicked);
    connect(ui->updateTreeButtonJournal, &QPushButton::clicked, this, &MainWindow::updateTreeClicked);

    connect(paginationBarJournal,
            &PaginationBar::pageChanged,
            this,
            &MainWindow::onJournalPageChanged);
}

void MainWindow::onJournalPageChanged(int page)
{
    while (QLayoutItem *item = ui->scrollLayoutJournal->takeAt(0)) {
        if (QWidget *widget = item->widget()) {
            widget->deleteLater();
        }
        delete item;
    }

    QList<LogsR> arr = journalService->getLogs(journalSettings->groupsWithSensors, journalSettings->status,
                                               journalSettings->cmp, journalSettings->start_time,
                                               journalSettings->end_time, page, 24);
    for(int i = 0; i < arr.size(); ++i) {
        LogWidget *logWidget = new LogWidget(translate, arr[i].getTime(), arr[i].getMessage(),
                                                   arr[i].getSensorId(), arr[i].getSensorGroup(),
                                                   arr[i].getThreatLevel(), ui->scrollWidgetJournal);
        logWidget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
        ui->scrollLayoutJournal->addWidget(logWidget);
    }
    if (arr.size() < 24) {
        QSpacerItem *spacer = new QSpacerItem(0, 0, QSizePolicy::Minimum, QSizePolicy::Expanding);
        ui->scrollLayoutJournal->addSpacerItem(spacer);
    }
}

void MainWindow::onSearchJournalClicked() {
    while (QLayoutItem *item = ui->scrollLayoutJournal->takeAt(0)) {
        if (QWidget *widget = item->widget()) {
            widget->deleteLater();
        }
        delete item;
    }

    journalSettings = getJournalDataSettings();

    int amount = journalService->getLogsAmount(journalSettings->groupsWithSensors, journalSettings->status,
                                               journalSettings->start_time, journalSettings->end_time);
    paginationBarJournal->setTotalPages((amount + 24 - 1)/ 24);

    QList<LogsR> arr = journalService->getLogs(journalSettings->groupsWithSensors, journalSettings->status,
                                               journalSettings->cmp, journalSettings->start_time,
                                               journalSettings->end_time, 1, 24);

    for(int i = 0; i < arr.size(); ++i) {
        LogWidget *logWidget = new LogWidget(translate, arr[i].getTime(), arr[i].getMessage(),
                                             arr[i].getSensorId(), arr[i].getSensorGroup(),
                                             arr[i].getThreatLevel(), ui->scrollWidgetJournal);
        logWidget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
        ui->scrollLayoutJournal->addWidget(logWidget);
    }
    if (arr.size() < 24) {
        QSpacerItem *spacer = new QSpacerItem(0, 0, QSizePolicy::Minimum, QSizePolicy::Expanding);
        ui->scrollLayoutJournal->addSpacerItem(spacer);
    }
}

JournalSettings* MainWindow::getJournalDataSettings() {
    QString time = ui->timeIntervalJournal->currentText();

    qint64 start_time, end_time;
    QTimeZone systemTimeZone = QTimeZone::systemTimeZone();
    QTimeZone spbTimeZone("Europe/Moscow");

    QDateTime now = QDateTime::currentDateTime();
    now.setTimeZone(systemTimeZone);
    now = now.toTimeZone(spbTimeZone);

    if (time == "За всё время") {
        start_time = 1;
        end_time = now.toSecsSinceEpoch();
    } else if (time == "За сегодня") {
        QDateTime startOfDay = now.date().startOfDay();
        start_time = startOfDay.toSecsSinceEpoch();
        end_time = now.toSecsSinceEpoch();
    } else if (time == "За вчера") {
        QDateTime startOfYesterday = now.addDays(-1).date().startOfDay();
        QDateTime endOfYesterday = startOfYesterday.addDays(1).addSecs(-1);
        start_time = startOfYesterday.toSecsSinceEpoch();
        end_time = endOfYesterday.toSecsSinceEpoch();
    } else if (time == "За последние 7 дней") {
        QDateTime startOf7DaysAgo = now.addDays(-6).date().startOfDay();
        start_time = startOf7DaysAgo.toSecsSinceEpoch();
        end_time = now.toSecsSinceEpoch();
    } else {
        start_time = 1;
        end_time = now.toSecsSinceEpoch();
    }

    QString searchQuery = ui->searchJournal->text().trimmed();
    searchQuery = searchQuery.toLower();

    QMap<QString, QList<QString>> sensorsMap;

    for (int i = 0; i < ui->treeJournal->topLevelItemCount(); ++i) {
        QTreeWidgetItem *groupItem = ui->treeJournal->topLevelItem(i);
        QString groupName = groupItem->data(0, Qt::UserRole).toString();

        QList<QString> sensorIds;
        for (int j = 0; j < groupItem->childCount(); ++j) {
            QTreeWidgetItem *sensorItem = groupItem->child(j);

            if (sensorItem->checkState(0) == Qt::Checked) {
                QString sensorId = sensorItem->data(0, Qt::UserRole).toString();
                if (searchQuery.isEmpty() || sensorId.toLower().contains(searchQuery)) {
                    sensorIds.append(sensorId);
                }
            }
        }

        if (!sensorIds.isEmpty()) {
            sensorsMap[groupName] = sensorIds;
        }
    }

    bool cmp = ui->sortJournal->currentText() == "По времени" ? 0 : 1;

    QList<int> status;
    QString statusText = ui->statusJournal->currentText();
    if (statusText == "Отладка"){
        status = {0};
    } else if (statusText == "Информация"){
        status = {1};
    } else if (statusText == "Предупреждение"){
        status = {2};
    } else if (statusText == "Ошибка"){
        status = {3};
    } else if (statusText == "Экстренно"){
        status = {4};
    }

    return new JournalSettings(sensorsMap, start_time, end_time, cmp, status);
}

void MainWindow::onTreeJournalChanged(QTreeWidgetItem *item, int column)
{
    Q_UNUSED(column);
}

void MainWindow::onSearchJournalTextChanged(const QString &text)
{
    Q_UNUSED(text);
    if (text.isEmpty()) {
        ui->searchJournal->setStyleSheet(R"(
            QLineEdit {
            width: 778px;
            height: 60px;
            border: 2px solid #DCD174;
            font-family: Inter;
            font-size: 26px;
            font-weight: 400;
            line-height: 31.47px;
            text-align: left;
            background: #00000000;
            color: #a6a6a6;
            }

        )");
    } else {
        ui->searchJournal->setStyleSheet(R"(
            QLineEdit {
            width: 778px;
            height: 60px;
            border: 2px solid #DCD174;
            font-family: Inter;
            font-size: 26px;
            font-weight: 400;
            line-height: 31.47px;
            text-align: left;
            background: #00000000;
            color: #13385F;
            }
        )");
    }
}

void MainWindow::SetupIncidentTab() {
    loadSensorsTree(ui->treeIncidents);

    connect(ui->treeIncidents, &QTreeWidget::itemChanged, this, &MainWindow::onTreeIncidentsChanged);

    connect(ui->searchIncedents,
            &QLineEdit::textChanged,
            this,
            &MainWindow::onSearchIncedentsTextChanged);

    ui->timeIntervalIncedents->addItems(
        {"За всё время", "За сегодня", "За вчера", "За последние 7 дней"});

    settingsIncident = getIncidentDataSettings();
    int amount = alarmsService->getAlarmsAmount(settingsIncident->groupsWithSensors, settingsIncident->start_time, settingsIncident->end_time);
    paginationBarIncident = new PaginationBar((amount + 24 - 1)/ 24, this);
    QList<AlarmR> arr = alarmsService->getAlarms(settingsIncident->groupsWithSensors, settingsIncident->start_time,
                                                 settingsIncident->end_time, 1, 24);
    for(int i = 0; i < arr.size(); ++i) {
        AlarmWidget *a = new AlarmWidget(translate, arr[i].getSensorId(), arr[i].getSensorGroup(),
                                         arr[i].getStartTime().left(10), arr[i].getStartTime().mid(11, 15),
                                         arr[i].getEndTime(), sensorService, ui->scrollWidgetIncidents);
        connect(a, &AlarmWidget::dialogClosedFromWidget, this, &MainWindow::ondialogClosedFromWidget);
        a->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
        ui->scrollLayoutIncidents->addWidget(a);
    }
    if (arr.size() < 24) {
        QSpacerItem *spacer = new QSpacerItem(0, 0, QSizePolicy::Minimum, QSizePolicy::Expanding);
        ui->scrollLayoutIncidents->addSpacerItem(spacer);
    }
    ui->paginationBarIncedentsLayout->addStretch();
    ui->paginationBarIncedentsLayout->addWidget(paginationBarIncident);
    ui->paginationBarIncedentsLayout->addStretch();

    connect(ui->searchIncidents, &QPushButton::clicked, this, &MainWindow::onSearchIncidentsClicked);
    connect(ui->updateTreeButtonIncident, &QPushButton::clicked, this, &MainWindow::updateTreeClicked);

    connect(paginationBarIncident,
            &PaginationBar::pageChanged,
            this,
            &MainWindow::onIncidentsPageChanged);
}

void MainWindow::onIncidentsPageChanged(int page)
{
    while (QLayoutItem *item = ui->scrollLayoutIncidents->takeAt(0)) {
        if (QWidget *widget = item->widget()) {
            widget->deleteLater();
        }
        delete item;
    }

    QList<AlarmR> arr = alarmsService->getAlarms(settingsIncident->groupsWithSensors, settingsIncident->start_time,
                                                 settingsIncident->end_time, page, 24);
    for(int i = 0; i < arr.size(); ++i) {
        AlarmWidget *alarmWidget = new AlarmWidget(translate, arr[i].getSensorId(), arr[i].getSensorGroup(),
                                                   arr[i].getStartTime().left(10), arr[i].getStartTime().mid(11, 15),
                                                   arr[i].getEndTime(), sensorService, ui->scrollWidgetIncidents);
        alarmWidget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
        ui->scrollLayoutIncidents->addWidget(alarmWidget);
    }
    if (arr.size() < 24) {
        QSpacerItem *spacer = new QSpacerItem(0, 0, QSizePolicy::Minimum, QSizePolicy::Expanding);
        ui->scrollLayoutIncidents->addSpacerItem(spacer);
    }
}

void MainWindow::onSearchIncidentsClicked() {
    while (QLayoutItem *item = ui->scrollLayoutIncidents->takeAt(0)) {
        if (QWidget *widget = item->widget()) {
            widget->deleteLater();
        }
        delete item;
    }
    settingsIncident = getIncidentDataSettings();
    int amount = alarmsService->getAlarmsAmount(settingsIncident->groupsWithSensors, settingsIncident->start_time, settingsIncident->end_time);
    paginationBarIncident->setTotalPages((amount + 24 - 1)/ 24);
    QList<AlarmR> arr = alarmsService->getAlarms(settingsIncident->groupsWithSensors, settingsIncident->start_time,
                                                 settingsIncident->end_time, 1, 24);
    for(int i = 0; i < arr.size(); ++i) {
        AlarmWidget *a = new AlarmWidget(translate, arr[i].getSensorId(), arr[i].getSensorGroup(),
                                         arr[i].getStartTime().left(10), arr[i].getStartTime().mid(11, 15),
                                         arr[i].getEndTime(), sensorService, ui->scrollWidgetIncidents);
        a->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
        ui->scrollLayoutIncidents->addWidget(a);
    }
    if (arr.size() < 24) {
        QSpacerItem *spacer = new QSpacerItem(0, 0, QSizePolicy::Minimum, QSizePolicy::Expanding);
        ui->scrollLayoutIncidents->addSpacerItem(spacer);
    }
}

AlarmSettings* MainWindow::getIncidentDataSettings() {
    QString time = ui->timeIntervalIncedents->currentText();

    qint64 start_time, end_time;
    QTimeZone systemTimeZone = QTimeZone::systemTimeZone();
    QTimeZone spbTimeZone("Europe/Moscow");

    QDateTime now = QDateTime::currentDateTime();
    now.setTimeZone(systemTimeZone);
    now = now.toTimeZone(spbTimeZone);

    if (time == "За всё время") {
        start_time = 1;
        end_time = now.toSecsSinceEpoch();
    } else if (time == "За сегодня") {
        QDateTime startOfDay = now.date().startOfDay();
        start_time = startOfDay.toSecsSinceEpoch();
        end_time = now.toSecsSinceEpoch();
    } else if (time == "За вчера") {
        QDateTime startOfYesterday = now.addDays(-1).date().startOfDay();
        QDateTime endOfYesterday = startOfYesterday.addDays(1).addSecs(-1);
        start_time = startOfYesterday.toSecsSinceEpoch();
        end_time = endOfYesterday.toSecsSinceEpoch();
    } else if (time == "За последние 7 дней") {
        QDateTime startOf7DaysAgo = now.addDays(-6).date().startOfDay();
        start_time = startOf7DaysAgo.toSecsSinceEpoch();
        end_time = now.toSecsSinceEpoch();
    } else {
        start_time = 1;
        end_time = now.toSecsSinceEpoch();
    }

    QString searchQuery = ui->searchIncedents->text().trimmed();
    searchQuery = searchQuery.toLower();

    QMap<QString, QList<QString>> sensorsMap;

    for (int i = 0; i < ui->treeIncidents->topLevelItemCount(); ++i) {
        QTreeWidgetItem *groupItem = ui->treeIncidents->topLevelItem(i);
        QString groupName = groupItem->data(0, Qt::UserRole).toString();

        QList<QString> sensorIds;
        for (int j = 0; j < groupItem->childCount(); ++j) {
            QTreeWidgetItem *sensorItem = groupItem->child(j);

            if (sensorItem->checkState(0) == Qt::Checked) {
                QString sensorId = sensorItem->data(0, Qt::UserRole).toString();
                if (searchQuery.isEmpty() || sensorId.toLower().contains(searchQuery)) {
                    sensorIds.append(sensorId);
                }
            }
        }

        if (!sensorIds.isEmpty()) {
            sensorsMap[groupName] = sensorIds;
        }
    }

    return new AlarmSettings(sensorsMap, start_time, end_time);
}

void MainWindow::onTreeIncidentsChanged(QTreeWidgetItem *item, int column)
{
    Q_UNUSED(column);
}

void MainWindow::onSearchIncedentsTextChanged(const QString &text)
{
    Q_UNUSED(text);
    if (text.isEmpty()) {
        ui->searchIncedents->setStyleSheet(R"(
            QLineEdit {
            width: 778px;
            height: 60px;
            border: 2px solid #DCD174;
            font-family: Inter;
            font-size: 26px;
            font-weight: 400;
            line-height: 31.47px;
            text-align: left;
            background: #00000000;
            color: #a6a6a6;
            }

        )");
    } else {
        ui->searchIncedents->setStyleSheet(R"(
            QLineEdit {
            width: 778px;
            height: 60px;
            border: 2px solid #DCD174;
            font-family: Inter;
            font-size: 26px;
            font-weight: 400;
            line-height: 31.47px;
            text-align: left;
            background: #00000000;
            color: #13385F;
            }
        )");
    }
}

void MainWindow::loadSensorsTree(QTreeWidget *treeWidget)
{
    if (!treeWidget) return;

    QTreeWidget *bufferTree = new QTreeWidget();

    sensorGroupTree tree = sensorService->getSensorGroupsTree();

    QStringList groups = tree.groupToLocalGroup.keys();
    std::sort(groups.begin(), groups.end());

    for (const QString &group : groups) {
        QTreeWidgetItem *groupItem = new QTreeWidgetItem(bufferTree);

        const QString &localizedGroupName = tree.groupToLocalGroup[group];
        groupItem->setText(0, localizedGroupName);
        groupItem->setData(0, Qt::UserRole, group);

        if (tree.groupToSensorWithLocal.contains(group)) {
            const QMap<QString, QString> &sensors = tree.groupToSensorWithLocal[group];

            for (auto it = sensors.begin(); it != sensors.end(); ++it) {
                const QString &sensorId = it.key();
                const QString &sensorName = it.value();

                nameToId[sensorName] = sensorId;

                QTreeWidgetItem *sensorItem = new QTreeWidgetItem(groupItem);
                sensorItem->setText(0, sensorName);
                sensorItem->setCheckState(0, Qt::Checked);
                sensorItem->setData(0, Qt::UserRole, sensorId);
            }
        }
    }

    treeWidget->clear();
    moveTopLevelItems(bufferTree, treeWidget);

    delete bufferTree;
}


void MainWindow::moveTopLevelItems(QTreeWidget *source, QTreeWidget *destination)
{
    while (source->topLevelItemCount() > 0) {
        QTreeWidgetItem *item = source->takeTopLevelItem(0);
        destination->addTopLevelItem(item);
    }
}

void MainWindow::SetupSensorTab()
{
    QScrollArea *scrollArea = new QScrollArea(this);
    scrollArea->setStyleSheet("QScrollArea {"
                              "    background: transparent;"
                              "    border: none;"
                              "}"
                              "QScrollBar:vertical {"
                              "    background: #ebebeb;"
                              "    width: 10px;"
                              "    border-radius: 5px;"
                              "}"
                              "QScrollBar::handle:vertical {"
                              "    background: #6d6d6d;"
                              "    border-radius: 5px;"
                              "    min-height: 20px;"
                              "}"
                              "QScrollBar::up-arrow:vertical, QScrollBar::down-arrow:vertical {"
                              "    border: none;"
                              "    background: none;"
                              "    color: none;"
                              "}"
                              "QScrollBar::sub-line:vertical, QScrollBar::add-line:vertical {"
                              "    background: transparent;"
                              "    border: none;"
                              "}"
                              "QScrollBar::add-page:vertical, QScrollBar::sub-page:vertical {"
                              "    background: transparent;"
                              "}");
    scrollArea->setWidgetResizable(true);
    scrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
    scrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);

    widgetContainer = new QWidget(scrollArea);
    widgetContainer->setStyleSheet("background: transparent;");
    layout = new FlowLayout(widgetContainer, 10, 10, 10);

    widgetContainer->setLayout(layout);
    scrollArea->setWidget(widgetContainer);
    ui->sensorsLayout->addWidget(scrollArea);

    connect(ui->search, &QLineEdit::textChanged, this, &MainWindow::onSearchTextChanged);
    ui->showHiddenSelect->addItems({"Да", "Нет"});
    connect(ui->groupSelect,
            QOverload<int>::of(&QComboBox::currentIndexChanged),
            this,
            &MainWindow::onGroupSelected);
    connect(ui->showHiddenSelect,
            QOverload<int>::of(&QComboBox::currentIndexChanged),
            this,
            &MainWindow::onShowHiddenSelected);

    loadSensorGroups();
}

void MainWindow::updateTreeClicked()
{
    QObject *senderObj = sender();
    if (!senderObj) return;

    if (senderObj == ui->updateTreeButtonJournal) {
        ui->treeJournal->hide();
        loadSensorsTree(ui->treeJournal);
        ui->treeJournal->show();
    } else if (senderObj == ui->updateTreeButtonIncident) {
        ui->treeIncidents->hide();
        loadSensorsTree(ui->treeIncidents);
        ui->treeIncidents->show();
    }
}

//TODO: посмотреть что с таймером

void MainWindow::startRefreshTimer()
{
    QTimer *refreshTimer = new QTimer(this);

    connect(refreshTimer, &QTimer::timeout, this, [this]() {
        if (ui->tabWidget->currentWidget() == ui->sensorsTab) {
            updateDisplayedWidgets();
        }
        TranslateUpdate();
    });

    refreshTimer->start(5000); //5 sec
}


void MainWindow::TranslateUpdate() {
    translate = sensorService->getTranslate();
}

void MainWindow::showSensorDialog(SensorWidget *sensor)
{
    SensorDialog *dialog = new SensorDialog(this, sensor, httpClient);
    dialog->setWindowModality(Qt::ApplicationModal);

    connect(dialog, &SensorDialog::resultReady, this, &MainWindow::onSensorDialogFinished);

    dialog->exec();
}

void MainWindow::onSensorDialogFinished(int result)
{
    switch (result) {
    case SensorDialog::SaveSuccess:
        updateDisplayedWidgets();
        break;

    case SensorDialog::SaveError:
        QMessageBox::critical(nullptr, "Ошибка", "Данные не сохранены, попробуйте еще раз");
        break;

    case SensorDialog::NoSave:
        updateDisplayedWidgets();
        break;

    default:
        break;
    }
}

void MainWindow::loadSensorGroups()
{
    QMap<QString, QString> groupsMap = sensorService->getLocalizedSensorGroups();

    if (groupsMap.isEmpty()) {
        QTimer::singleShot(5000, this, &MainWindow::loadSensorGroups);
        return;
    }

    ui->groupSelect->clear();
    for (auto it = groupsMap.begin(); it != groupsMap.end(); ++it) {
        if(it.key() == "*SYSTEM") {
            continue;
        }
        ui->groupSelect->addItem(it.key(), it.value());
    }

    if (!groupsMap.isEmpty()) {
        loadSensors(groupsMap[groupsMap.firstKey()]);
    }
}

void MainWindow::loadSensors(const QString &group)
{
    QList<Sensor> sensors = sensorService->getSensors(group);

    const auto &existingWidgets = widgetContainer->findChildren<SensorWidget *>();
    for (SensorWidget *widget : existingWidgets) {
        delete widget;
    }

    layout->clear();

    for (const Sensor &sensor : sensors) {
        if(sensor.id == "*NAME") {
            continue;
        }
        SensorWidget *s = new SensorWidget(nullptr, sensor);
        layout->addWidget(s);

        connect(s, &SensorWidget::clicked, this, &MainWindow::showSensorDialog);
    }

    widgetContainer->update();
}

void MainWindow::updateDisplayedWidgets()
{
    QString selectedGroup = ui->groupSelect->currentData().toString();
    QString showHidden = ui->showHiddenSelect->currentText();
    QString searchText = ui->search->text();

    // Загружаем датчики только для выбранной группы
    QList<Sensor> sensors = sensorService->getSensors(selectedGroup);

    // Храним уже добавленные виджеты
    QMap<QString, SensorWidget *> existingWidgets;

    // Сохраняем существующие виджеты и их сенсоры для последующего обновления
    const auto &widgets = widgetContainer->findChildren<SensorWidget *>();
    for (SensorWidget *widget : widgets) {
        existingWidgets[widget->getSensor().id] = widget;
    }

    layout->clear(); // Очищаем layout, но не удаляем сами виджеты

    // Проходим по новым датчикам и добавляем их в layout, если они ещё не добавлены
    for (const Sensor &sensor : sensors) {
        SensorWidget *widget = nullptr;

        if(sensor.id == "*NAME") {
            continue;
        }

        // Проверяем, существует ли виджет для данного сенсора
        if (existingWidgets.contains(sensor.id)) {
            widget = existingWidgets[sensor.id];
            widget->setSensor(sensor); // Обновляем данные существующего виджета
        } else {
            widget = new SensorWidget(nullptr, sensor);
            connect(widget, &SensorWidget::clicked, this, &MainWindow::showSensorDialog);
        }

        // Применяем фильтрацию по условиям
        bool matchesHidden = (showHidden == "Да") || !sensor.isHide;
        bool matchesSearch = sensor.name.contains(searchText, Qt::CaseInsensitive);

        if (matchesHidden && matchesSearch) {
            layout->addWidget(widget);
            widget->show();
        } else {
            widget->hide();
        }
    }

    widgetContainer->update(); // Обновляем виджеты в контейнере
}

void MainWindow::onGroupSelected(int index)
{
    Q_UNUSED(index);
    loadSensors(ui->groupSelect->currentText());
    updateDisplayedWidgets();
}

void MainWindow::onShowHiddenSelected(int index)
{
    Q_UNUSED(index);
    updateDisplayedWidgets();
}

void MainWindow::onSearchTextChanged(const QString &text)
{
    Q_UNUSED(text);
    if (text.isEmpty()) {
        ui->search->setStyleSheet(R"(
            QLineEdit {
            width: 778px;
            height: 60px;
            border: 2px solid #DCD174;
            font-family: Inter;
            font-size: 26px;
            font-weight: 400;
            line-height: 31.47px;
            text-align: left;
            background: #00000000;
            color: #a6a6a6;
            }

        )");
    } else {
        ui->search->setStyleSheet(R"(
            QLineEdit {
            width: 778px;
            height: 60px;
            border: 2px solid #DCD174;
            font-family: Inter;
            font-size: 26px;
            font-weight: 400;
            line-height: 31.47px;
            text-align: left;
            background: #00000000;
            color: #13385F;
            }
        )");
    }
    updateDisplayedWidgets();
}

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