#pragma once



#include "Core/Base/ThreadManager.h"
#include "../Data_Source/export.h"
#include "../State_Report/State_Report.h"
#include "../global_include.h"
#include "Ucoro_Drogon_Glue.h"
#include "Config.h"
#include <drogon/drogon.h>

#include "Config.h"

#include "../../Radarcape_Core/cpp-httplib/httplib.h"
#include "../Data_Source/export.h"
#include "Core/Net_Adapter/Net_Adapter.h"
#include "libarchive.h"
#include <filesystem>
#include <list>
#include <utility>

// 集中 管理日志
using namespace Psc;
extern BaseLogger* server_logger;
std::string to_file_name(std::string str);
std::string inet_address_to_string(const trantor::InetAddress &addr);

using Serial_Number_Type = unsigned int;
struct Debug_Logger_Info_Manager {
    void push_info(const std::string& content);
    std::string get_info(Serial_Number_Type serial_number);
    Serial_Number_Type get_cur_serial_number();
    struct Info {
        Serial_Number_Type sequence;
        std::string content;
    };
    std::list<Info> info_list;
    JSON to_json();
private:
    // 最大总长度
    static constexpr size_t max_length = 1000 * 300;
    // 当前总长度
    size_t current_total_length = 0;
    Serial_Number_Type cur_serial_number = 0;
    std::mutex mtx;
};
extern Debug_Logger_Info_Manager debug_logger_info_manager;



#define RET_OK                                                                                                         \
    res.status = StatusCode::OK_200;                                                                                   \
    res.set_content("{\"status\": 200}", "application/json");
    inline JSON warp(const JSON& data) {
    // Json ret = Json::object();
    // ret.append({"status", 200});
    // ret.append({"data", data});
    // return ret;
    return data;
}



#define HTTP_Param const drogon::HttpRequestPtr& req, const drogon::HttpResponsePtr& res

class Web_Server {
public:
    std::string update = "update_";
    std::string insert = "insert_";
    std::string remove = "remove_";
    std::string search = "search_";
    std::string rise = "rise_";
    std::string fall = "fall_";
    using Handler = std::function<void(const drogon::HttpRequestPtr&, const drogon::HttpResponsePtr&)>;
    using CoroHandler = std::function<drogon::Task<>(const drogon::HttpRequestPtr&, const drogon::HttpResponsePtr&)>;
    bool listen(const std::string& host, int port);

    ~Web_Server() = default;





    static void stop() {
        std::cout << "开始停止web服务" << std::endl;
        drogon::app().quit();
    }

    Web_Server& Post(const std::string& pattern, Handler handler) {
        drogon::app().registerHandler(
            pattern,
            [handler](const drogon::HttpRequestPtr& request,
                      std::function<void(const drogon::HttpResponsePtr&)>&& callback) {
                auto resp = drogon::HttpResponse::newHttpResponse();
                resp->setContentTypeCode(drogon::CT_APPLICATION_JSON);

                handler(request, resp);

                callback(resp);
            },
            {drogon::Post}
        );

        return *this;
    }

    Web_Server& PostCoro(const std::string& pattern, CoroHandler handler) {
        drogon::app().registerHandler(
            pattern,
            [handler = std::move(handler)](
                const drogon::HttpRequestPtr& request,
                std::function<void(const drogon::HttpResponsePtr&)>&& callback) {
                auto resp = drogon::HttpResponse::newHttpResponse();
                resp->setContentTypeCode(drogon::CT_APPLICATION_JSON);

                drogon::async_run(
                    [handler, request, resp, callback = std::move(callback)]() mutable -> drogon::Task<> {
                        try {
                            co_await handler(request, resp);
                        } catch (const std::exception& error) {
                            resp->setStatusCode(drogon::k500InternalServerError);
                            resp->setBody(Psc::JSON::object({{"error", std::string(error.what())}}).to_json_string());
                        } catch (...) {
                            resp->setStatusCode(drogon::k500InternalServerError);
                            resp->setBody(Psc::JSON::object({{"error", "unknown error"}}).to_json_string());
                        }
                        callback(resp);
                        co_return;
                    });
            },
            {drogon::Post}
        );

        return *this;
    }

    Web_Server& Get(const std::string& pattern, Handler handler) {
        drogon::app().registerHandlerViaRegex(
            pattern,
            [handler](const drogon::HttpRequestPtr& request,
                      std::function<void(const drogon::HttpResponsePtr&)>&& callback) {
                auto resp = drogon::HttpResponse::newHttpResponse();
                resp->setContentTypeCode(drogon::CT_APPLICATION_JSON);

                handler(request, resp);

                callback(resp);
            },
            {drogon::Get}
        );

        return *this;
    }

    Web_Server& GetCoro(const std::string& pattern, CoroHandler handler) {
        drogon::app().registerHandlerViaRegex(
            pattern,
            [handler = std::move(handler)](
                const drogon::HttpRequestPtr& request,
                std::function<void(const drogon::HttpResponsePtr&)>&& callback) {
                auto resp = drogon::HttpResponse::newHttpResponse();
                resp->setContentTypeCode(drogon::CT_APPLICATION_JSON);

                drogon::async_run(
                    [handler, request, resp, callback = std::move(callback)]() mutable -> drogon::Task<> {
                        try {
                            co_await handler(request, resp);
                        } catch (const std::exception& error) {
                            resp->setStatusCode(drogon::k500InternalServerError);
                            resp->setBody(Psc::JSON::object({{"error", std::string(error.what())}}).to_json_string());
                        } catch (...) {
                            resp->setStatusCode(drogon::k500InternalServerError);
                            resp->setBody(Psc::JSON::object({{"error", "unknown error"}}).to_json_string());
                        }
                        callback(resp);
                        co_return;
                    });
            },
            {drogon::Get}
        );

        return *this;
    }
};


// 这个对象不释放





class Mlat_MSG {
public:
    explicit Mlat_MSG(const std::shared_ptr<SSR::Mode_Msg>& first) { list.push_back(first);}
    [[nodiscard]] std::optional<std::string> icao() const {
        auto a = list[0];
        auto t = a->type;
        if (t == SSR::Mode_Msg::T::S7 || t == SSR::Mode_Msg::T::S14) {
            return dynamic_cast<SSR::Mode_S_Msg*>(a.get())->icao;
        }
        return std::nullopt;
    }
    [[nodiscard]] std::string msg_hex() const { return list[0]->msg_hex;}
    [[nodiscard]] SSR::Mode_Msg::T type() const { return static_cast<SSR::Mode_Msg::T>(list[0]->type);}
    [[nodiscard]] SSR::MLAT_timestamp& timestamp() const { return list[0]->mlat_timestamp;}
    [[nodiscard]] std::shared_ptr<SSR::Data_Source_Interface> data_source() const { return list[0]->source;}
    void add(const std::shared_ptr<SSR::Mode_Msg>& t) {
        list.push_back(t);
    }
    [[nodiscard]] size_t size() const { return list.size(); }
    std::vector<std::shared_ptr<SSR::Mode_Msg>> list;
};





class Mlat_Handler {
public:
    std::list<Mlat_MSG> get_all() {
        std::lock_guard<std::mutex> gg(ok_mtx);
        if (ok_list.empty()) return {};
        std::list<Mlat_MSG> ret;
        std::swap(ok_list, ret);
        return ret;
    }

    void push(const std::shared_ptr<SSR::Mode_Msg>& msg) {
        std::lock_guard<std::mutex> g(mtx);

        if (list.empty()) {
            list.emplace_back(msg);
            return;
        }

        auto time = msg->mlat_timestamp;
        auto p = list.rbegin();

        while (p != list.rend()) {
            auto cur_time = p->timestamp();
            // 往前最多找3秒
            if (cur_time.daysec + 3 < time.daysec) {
                std::lock_guard<std::mutex> gg(ok_mtx);
                ok_list.splice(ok_list.end(), list, list.begin(), p.base());
                return;
            }
            if (p->msg_hex() == msg->msg_hex) {
                p->add(msg);
                return;
            }
            ++p;
        }
        list.insert(p.base(), Mlat_MSG(msg));
    }
protected:
    std::list<Mlat_MSG> ok_list;
    std::list<Mlat_MSG> list;
    std::mutex ok_mtx;
    std::mutex mtx;
};





class Global : public Config, public Singleton<Global>{
public:
    // asio::io_context ctx;
    std::atomic<bool> init_ok{false};
    Global();
    ~Global();
    Detach_Thread_Manager thread_manager;
    std::shared_ptr<Data_Source> source(const std::string& data_source_key) {
        return mode_acs.data_source_config.map.get(data_source_key).value_or(nullptr);
    }
    std::shared_ptr<Data_Source> total_source() {
        for (auto i : mode_acs.data_source_config.map.list())
        {
            if (i->enable) return i;
        }
        return mode_acs.data_source_config.map.list().at(0);
    }
    Web_Server svr;
    std::string api = "/api/";
    Mlat_Handler mlat_handler;
    void init_web_server();
    void handle_old_logs();
    std::time_t start_server_time;
    DELETE_COPY(Global)
};



void handle_buffer_muti_start(std::string& buffer, const std::string& data, const std::set<std::string>& prefix_list,
                              const std::function<void(std::string&)>& callback);
void handle_buffer_head_tail(std::string& buffer, const std::string& data, const std::string& prefix,
                             const std::string& suffix, const std::function<void(std::string&)>& callback);

