#include "mainwindow.h"

#include <QtCore/qlist.h>
#include <QtCore/qobject.h>

#include <QDebug>
#include <QPushButton>
#include <QWidget>

#include "backendapimanager.h"
#include "global.h"
#include "jobs.h"
#include "loadingWidget.h"
#include "logger.h"
#include "ui_mainwindow.h"

// 定义 ANzI 转义序列来设置颜色
#define ANSI_COLOR_GREEN "\x1B[32m"
#define ANSI_COLOR_RESET "\x1B[0m"
#include <QMessageBox>
#include <exception>

MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) {
    try {
        this->setWindowFlags(Qt::FramelessWindowHint);
        // this->setWindowState(Qt::WindowMaximized);  // Maximizes the window
        this->setFixedSize(1000, 600);
        ui->setupUi(this);
        LoadingWidget::init(ui->stackedWidget);

        initializeAnimate();
        initialMqttService();

        pageFactories[ui->btnNew] = new AddressFactory();
        pageFactories[ui->btnBlastProject] = new BlastProjectFactory();
        pageFactories[ui->btnEquipment] = new EquipmentFactory();
        pageFactories[ui->btnDet] = new DetInfoFactory();
        pageFactories[ui->btnBlastOper] = new BlastOperationFactory();
        pageFactories[ui->btnRecord] = new BlastRecordFactory();

        connect(ui->btnToggle, &QPushButton::clicked, this, &MainWindow::onToggleButtonClicked);
        for (auto *widget : left_button_station) {
            QPushButton *button = qobject_cast<QPushButton *>(widget);
            if (button) {
                connect(button, &QPushButton::clicked, this,
                        [this, button] { onButtonClicked(button); });
            }
        }
        initDateTime();
        initialBtnSerial();
        // initialGPSSerial();
        ui->labLat->setText("经度： " + lat);
        ui->labLon->setText("维度： " + lon);
        connect(ui->btnClose, &QPushButton::clicked, this, &MainWindow::close);
        connect(this, &MainWindow::projectTitleChanged, this, &MainWindow::updateProjectTitleLabel);
    } catch (const std::exception &ex) {
        Logger::getInstance().error(QString("Application crashed: %1").arg(ex.what()));
        QMessageBox::critical(this, "Error", QString("Application crashed: %1").arg(ex.what()));
        throw;  // rethrow to allow further handling if needed
    } catch (...) {
        Logger::getInstance().error("Application crashed: Unknown exception");
        QMessageBox::critical(this, "Error", "Application crashed: Unknown exception");
        throw;
    }
}

void MainWindow::updateProjectTitleLabel(const QString &newTitle) {
    ui->projectTitleLable->setText(newTitle);
}

void MainWindow::setProjectTitle(const QString &newTitle) {
    if (m_currentProjectTitle != newTitle) {
        m_currentProjectTitle = newTitle;

        // Emit the signal to notify listeners (like our QLabel slot)
        emit projectTitleChanged(m_currentProjectTitle);
    }
}

void MainWindow::initializeAnimate() {
    move(200, 200);
    animate_leftFrame = new QPropertyAnimation(ui->leftFrame, "minimumWidth");
    animate_leftFrame->setDuration(300);
    for (QObject *child : ui->left_buttonsBox->children()) {
        if (qobject_cast<QWidget *>(child)) {
            left_button_station.append(qobject_cast<QWidget *>(child));
        }
    }
}

void MainWindow::onToggleButtonClicked() {
    // 执行动画
    JOBS ::btn_animation(ui->leftFrame, animate_leftFrame);
    for (QWidget *b : left_button_station) {
        b->setProperty("spread", !b->property("spread").toBool());
        b->setStyleSheet(b->styleSheet());
    }
}

// 选中按钮
void MainWindow::onButtonClicked(QPushButton *button) {
    setStyleSheets(static_cast<QPushButton *>(button));

    switchPage(static_cast<QPushButton *>(button));
}

void MainWindow::switchPage(QWidget *button) {
    LoadingWidget::showLoading(this, "请稍等");
    if (pageFactories.contains(button)) {
        PageFactory *factory = pageFactories[button];

        if (createdPageByButton.contains(button)) {
            QWidget *existingPage = createdPageByButton[button];
            existingPage->hide();
            ui->stackedWidget->removeWidget(existingPage);
            createdPageByButton.remove(button);
        }

        QWidget *newPage = factory->createPage(this);

        ui->stackedWidget->addWidget(newPage);
        ui->stackedWidget->setCurrentWidget(newPage);
        setProjectTitle(qobject_cast<QPushButton *>(button)->text());

        createdPageByButton.insert(button, newPage);
        int pageCount = ui->stackedWidget->count();
    }
    LoadingWidget::hideLoading();
}

void MainWindow::initialMqttService() {
    Logger::getInstance().info("Start init Mqtt server.");
    MqttClient *pcMqttInit = MqttClient::getInstance();
    // "hxgc/topic"
    QStringList topics = {MQTT_TOPIC_CAMPANY_PROJECTS};
    pcMqttInit->connectToMqttBroker("114.55.233.194", 1883, "hxgc", "hxgc123456", mqttClientId,
                                    topics);
    connect(pcMqttInit, &MqttClient::proMessageReceived, this,
            &MainWindow::handleMqttProjectsMessage);
    Logger::getInstance().info("Connect Mqtt server request sent.");
}

void MainWindow::handleMqttProjectsMessage(const QByteArray &message, const QMqttTopicName &topic) {
    QJsonDocument jsonDoc = QJsonDocument::fromJson(message);
    if (!jsonDoc.isNull() && jsonDoc.isObject()) {
        QJsonObject jsonObj = jsonDoc.object();
        if (jsonObj.contains("uuid") && jsonObj.contains("status")) {
            QJsonValue uuidValue = jsonObj["uuid"];
            QJsonValue statusValue = jsonObj["status"];
            if (statusValue.isString() &&
                statusValue.toString() == BlastStatus::Created) {  // "1" 未注册
                if (uuidValue.isNull()) {
                    qDebug() << "uuid 的值为 null";
                } else {
                    QString uuid = uuidValue.toString();
                    HProjectDao dao = HProjectDao(DatabaseManager::getInstance().getDatabase());
                    dao.updateBlastStatusByUuid(uuid, "2");
                }
            }
        } else if (jsonObj.contains("msgType") && jsonObj["msgType"].toString() == "safeCheck") {
            // 处理安全验证消息
            if (jsonObj["status"] != "ok") {
                QMessageBox::warning(this, "安全验证失败",
                                     QString("安全验证未通过，练习安全员确认"));
                return;
            }

            const QString addressUuid = jsonObj["addressUuid"].toString();
            QJsonArray addressList = backendAPIManager::getHAddresses();

            QList<QString> subAddressUuids = findAllChildUuids(addressList, addressUuid);
            HProjectDao dao = HProjectDao(DatabaseManager::getInstance().getDatabase());

            QList<QSharedPointer<HProject>> projects =
                dao.getRegistedProjectByAddressUuid(subAddressUuids);
            for (const auto &project : projects) {
                dao.updateBlastStatusByUuid(project->getUuid(), BlastStatus::SafeChecked);
            }
        }
    }
}

void MainWindow::setStyleSheets(QPushButton *selectedButton) {
    for (auto *b : left_button_station) {
        b->setProperty("selected", b == selectedButton);
        b->setStyleSheet(b->styleSheet());  // 刷新显示
    }
}

// 处理 MQTT 连接成功的槽函数
void MainWindow::onMqttConnected() {
    m_isMqttConnected = true;
    Logger::getInstance().info("Mqtt connected.");
}

void MainWindow::initialBtnSerial() {
    bool success;
    serialTool = SerialTool::getInstance(this, &success);
    connect(serialTool, &SerialTool::serialPortOpened, this, &MainWindow::onSerialToolCreated);
    serialTool->setupSerialPort();
    Logger::getInstance().info("Fire buttons initialized");
}

void MainWindow::onSerialToolCreated() {
    m_btnSerialInitialized = true;
    serialTool->releaseInstance();
    qDebug() << ANSI_COLOR_GREEN << "Serial tool initialized" << ANSI_COLOR_RESET;
    Logger::getInstance().info("SerialTool initialized");
}

void MainWindow::initialGPSSerial() {
    Logger::getInstance().info("开始初始化GPS");
    SerialGPSThread *threadGPS = new SerialGPSThread(this);
    connect(threadGPS, &SerialGPSThread::storedGNRMCDataUpdated, this,
            &MainWindow::handleStoredGNRMCData);
    threadGPS->start();
}
// 槽函数，用于接收 RMCData 数据
void MainWindow::handleStoredGNRMCData(const RMCData &data) {
    if (data.isValid) {
        lat = QString::number(data.latitude);
        lon = QString::number(data.longitude);
    } else {
        lat = "定位失败";
        lon = "定位失败";
    }

    ui->labLat->setText("经度： " + lat);
    ui->labLon->setText("纬度： " + lon);
    labLat = lat;
    labLon = lon;
}
void MainWindow::initDateTime() {
    timeThread = new TimeUpdateThread(this);
    connect(timeThread, &TimeUpdateThread::timeUpdated, this, &MainWindow::onTimeUpdated);
    timeThread->start();
}
void MainWindow::onTimeUpdated(const QString &timeString) { ui->dateTimeShow->setText(timeString); }

MainWindow::~MainWindow() {
    timeThread->stop();
    delete ui;
}

void MainWindow::mousePressEvent(QMouseEvent *event) {
    if (event->button() == Qt::LeftButton) {
        m_dragPosition = event->globalPos() - frameGeometry().topLeft();
        event->accept();
    }
}

void MainWindow::mouseMoveEvent(QMouseEvent *event) {
    if (event->buttons() & Qt::LeftButton) {
        move(event->globalPos() - m_dragPosition);
        event->accept();
    }
}

QList<QString> MainWindow::findAllChildUuids(const QJsonArray &addressArray,
                                             const QString targetUuid) {
    QList<QString> childrenUuids;

    for (const QJsonValue &value : addressArray) {
        if (!value.isObject()) continue;

        QJsonObject addressObj = value.toObject();
        QString currentUuid = addressObj["uuid"].toString();

        if (currentUuid == targetUuid) {
            // Found the target address, now collect all children UUIDs recursively
            if (addressObj.contains("children") && addressObj["children"].isArray()) {
                QJsonArray children = addressObj["children"].toArray();
                for (const QJsonValue &child : children) {
                    if (child.isObject()) {
                        QString childUuid = child.toObject()["uuid"].toString();
                        childrenUuids.append(childUuid);

                        // Also add any grandchildren
                        if (child.toObject().contains("children") &&
                            child.toObject()["children"].isArray()) {
                            QJsonArray grandchildren = child.toObject()["children"].toArray();
                            childrenUuids.append(findAllChildUuids(
                                grandchildren, child.toObject()["uuid"].toString()));
                        }
                    }
                }
                return childrenUuids;
            }
        } else if (addressObj.contains("children") && addressObj["children"].isArray()) {
            // Continue searching in children
            QJsonArray children = addressObj["children"].toArray();
            QList<QString> result = findAllChildUuids(children, targetUuid);
            if (!result.isEmpty()) {
                return result;
            }
        }
    }

    return childrenUuids;
}