#include "fileserver.h"
#include "logger.h"
#include <fstream>
#include <QJsonObject>
#include <QJsonDocument>
#include <QDir>

FileServer::FileServer(QObject *parent)
    : QObject{parent}
{
    moveToThread(&m_thread);
    connect(&m_thread, &QThread::started, this, &FileServer::run_hhttp_sever);
    run("0.0.0.0", 18000);
}

FileServer::~FileServer()
{
    stop();
}

std::string FileServer::addr() const
{
    return m_addr;
}

uint16_t FileServer::port() const
{
    return m_port;
}

bool FileServer::isRunning() const
{
    return m_thread.isRunning();
}

void FileServer::run(const char *addr, unsigned short port)
{
    m_addr = std::string(addr);
    m_port = port;
    LOG_DEBUG("file server start...");
    m_thread.start();
}

void FileServer::stop()
{
    m_server.stop();
    m_thread.quit();
    m_thread.wait();
}

void FileServer::run_hhttp_sever()
{

    // 心跳
    m_server.Get("/heartbeat", [&](const httplib::Request &req, httplib::Response &res) {
        QJsonDocument doc;
        QJsonObject obj = {
            {"message", QString("Connected")}
        };
        doc.setObject(obj);
        
        res.status = httplib::StatusCode::OK_200;
        res.set_content(doc.toJson().data(), "application/json");
    });

    // 画面配置文件更新接口
    m_server.Post("/update/monitor", [&](const httplib::Request &req, httplib::Response &res, const httplib::ContentReader &content_reader) {
        QJsonDocument doc;
        if (req.is_multipart_form_data()) {
            // NOTE: `content_reader` is blocking until every form data field is read
            // This approach allows streaming processing of large files
            std::vector<httplib::FormData> items;
            content_reader(
                [&](const httplib::FormData &item) {
                items.push_back(item);
                return true;
                },
                [&](const char *data, size_t data_length) {
                items.back().content.append(data, data_length);
                return true;
            });

            // Process the received items
            for (const auto& item : items) {
                if (item.filename.empty()) {
                    // Text field
                    // std::cout << "Field: " << item.name << " = " << item.content << std::endl;

                    QJsonObject obj = {
                        {"message", QString("File error")}
                    };
                    doc.setObject(obj);
                    
                    res.status = httplib::StatusCode::BadRequest_400;
                    res.set_content(doc.toJson().data(), "application/json");
                } else {
                    // File
                    QString currentPath = QDir::currentPath();
                    QString savePath = QString("%1/%2").arg(currentPath, "update");

                    QDir dir(savePath);
                    if(!dir.exists()) {
                        dir.mkpath(savePath);
                    }

                    QString filename = QString("%1/%2").arg(savePath, "monitor.xml");
                    std::ofstream ofs(filename.toStdString(), std::ios::binary);
                    if (!ofs) {
                        LOG_ERROR("open file failed: {}", filename.toStdString());
                        continue;
                    }

                    ofs.write(item.content.data(), item.content.size());
                    ofs.close();
                    LOG_INFO("monitor configure file successfully update");
                    emit monitorConfigureUpdate(filename);

                    QJsonObject obj = {
                        {"message", QString("'File successfully update")}
                    };
                    doc.setObject(obj);
                    
                    res.status = httplib::StatusCode::OK_200;
                    res.set_content(doc.toJson().data(), "application/json");
                }
            }
        } else {
            // std::string body;
            // content_reader([&](const char *data, size_t data_length) {
            //     body.append(data, data_length);
            //     return true;
            // });

            QJsonObject obj = {
                {"message", QString("File error")}
            };
            doc.setObject(obj);
            
            res.status = httplib::StatusCode::BadRequest_400;
            res.set_content(doc.toJson().data(), "application/json");
        }
    });

    m_server.listen(m_addr, m_port);
}