#ifndef PSC_GLOBAL_INCLUDE_H
#define PSC_GLOBAL_INCLUDE_H
#include <functional>
#include <iostream>
#include <map>
#include <mutex>
#include <optional>
#include <queue>
#include <stdexcept>
#include <string>
#include <string_view>
#include <thread>
#include <utility>
#include <vector>
#include "Psc_Cpp_Core/Statistics/Statistics.h"
#include "Psc_Cpp_Core/socket/ByteOrder.h"
#include "SSR/export.h"
class Global;
class Invalid_Http_Param final : public std::runtime_error {
public:
    using std::runtime_error::runtime_error;
};
[[noreturn]] inline void throw_invalid_http_param(const char* detail) {
    throw Invalid_Http_Param(detail);
}
#define CHECK_JSON_PARAM                                                                                               \
    auto o_params = Psc::try_parse_json(req->body().data());                                                           \
    if (!o_params.has_value()) {                                                                                       \
        throw_invalid_http_param("request body is not valid JSON");                                                    \
    }                                                                                                                  \
    auto& params = o_params.value();                                                                                   \
    auto that_json = &params;
#define HTTP_REQUIRE_VALUE(NAME, EXPRESSION)                                                                           \
    auto o_http_##NAME = (EXPRESSION);                                                                                 \
    if (!o_http_##NAME.has_value()) {                                                                                  \
        throw_invalid_http_param(#NAME);                                                                               \
    }                                                                                                                  \
    auto NAME = std::move(o_http_##NAME).value();
#define HTTP_REQUIRE_PTR(NAME, EXPRESSION)                                                                             \
    auto NAME = (EXPRESSION);                                                                                          \
    if ((NAME) == nullptr) {                                                                                           \
        throw_invalid_http_param(#NAME);                                                                               \
    }
#define HTTP_REQUIRE_TRUE(EXPRESSION, DETAIL)                                                                          \
    if (!(EXPRESSION)) {                                                                                               \
        throw_invalid_http_param(DETAIL);                                                                              \
    }
template <typename Value_Type>
class Ordered_List {
public:
    void swap(size_t i, size_t j) {
        std::lock_guard g(mtx);
        if (i >= _list.size() || j >= _list.size())
            return;
        std::swap(_list[i], _list[j]);
    }
    void push_back(Value_Type value) {
        std::lock_guard g(mtx);
        _list.push_back(value); // 添加默认值
    }
    void insert(int i, Value_Type value) {
        std::lock_guard g(mtx);
        _list.insert(_list.begin() + i, value);
    }
    Value_Type get(size_t i) {
        return _list[i];
    }
    void remove(size_t i) {
        std::lock_guard g(mtx);
        if (i >= _list.size())
            return;
        _list.erase(_list.begin() + i);
    }
    std::vector<Value_Type> list() {
        std::lock_guard g(mtx);
        return this->_list;
    }
    void clear() {
        list().clear();
    }
protected:
    std::mutex mtx;
    std::vector<Value_Type> _list;
};
template <typename Key_Type, typename Value_Type>
class Ordered_Map {
public:
    std::optional<Value_Type> get(Key_Type key) const {
        std::lock_guard g(mtx);
        auto it = _map.find(key);
        if (it != _map.end()) {
            return it->second;
        }
        return std::nullopt;
    }
    bool swap(size_t i, size_t j) {
        std::lock_guard g(mtx);
        if (i >= _list.size() || j >= _list.size())
            return false;
        std::swap(_list[i], _list[j]);
        // 更新 map 中的 value，假设你可以从 Value 中获取 key
        Key_Type key_i = _list[i]->key;
        Key_Type key_j = _list[j]->key;
        _map[key_i] = _list[i];
        _map[key_j] = _list[j];
        return true;
    }
    void push_back(Value_Type value) {
        std::lock_guard g(mtx);
        _list.push_back(value); // 添加默认值
        _map[value->key] = value; // 插入到 map
    }
    bool insert(int i, Value_Type value) {
        std::lock_guard g(mtx);
        if (i < 0 || static_cast<size_t>(i) > _list.size())
            return false;
        _list.insert(_list.begin() + i, value);
        _map[value->key] = value;
        return true;
    }
    Value_Type get(size_t i) {
        return _list[i];
    }
    std::optional<Value_Type> try_get(size_t i) {
        std::lock_guard g(mtx);
        if (i >= _list.size())
            return std::nullopt;
        return _list[i];
    }
    bool remove(size_t i) {
        std::lock_guard g(mtx);
        if (i >= _list.size())
            return false;
        Key_Type& key = _list[i]->key;
        _map.erase(key);
        _list.erase(_list.begin() + i);
        return true;
    }
    std::vector<Value_Type> list() const {
        std::lock_guard g(mtx);
        return this->_list;
    }
    // std::map<Key_Type, Value_Type> map(){
    //     std::lock_guard g(mtx);
    //     return this->_map;
    // }
    bool set_order(const std::vector<Key_Type>& keys) {
        std::lock_guard g(mtx);
        if (keys.size() != _list.size())
            return false;
        std::vector<Value_Type> reordered;
        reordered.reserve(_list.size());
        for (const auto& key : keys) {
            auto iterator = _map.find(key);
            if (iterator == _map.end())
                return false;
            reordered.push_back(iterator->second);
        }
        _list = std::move(reordered);
        return true;
    }
    void clear() {
        std::lock_guard g(mtx);
        _list.clear();
        _map.clear();
    }
protected:
    mutable std::mutex mtx;
    std::vector<Value_Type> _list;
    std::map<Key_Type, Value_Type> _map;
};
class Mode_AC_Statistic_Data {
public:
    Psc::JSON to_json() {
        std::lock_guard g(mtx);
        Psc::JSON ret = Psc::JSON::object();
        const auto messages_per_second = utc == std::time(nullptr) ? pre_second_num : 0;
        ret.append({"messages_per_second", messages_per_second});
        ret.append({"messages_total", total_num});
        ret.append({"length_errors_total", length_error_num.load()});
        return ret;
    }
    void add() {
        std::lock_guard g(mtx);
        add_inter();
    }
    void add_length_error() {
        std::lock_guard g(mtx);
        add_inter();
        length_error_num++;
    }
protected:
    std::atomic<size_t> length_error_num{};
    void add_inter() {
        total_num++;
        auto cur_time = std::time(nullptr);
        if (cur_time != utc) {
            utc = cur_time;
            pre_second_num = 0;
        }
        pre_second_num++;
    }
    std::mutex mtx;
    size_t pre_second_num{};
    size_t total_num{};
    time_t utc{};
};
class Statistic_Data {
public:
    time_t utc{};
    size_t pre_second_num{};
    size_t total_num{};
    [[nodiscard]] Psc::JSON to_json() const {
        Psc::JSON ret = Psc::JSON::object();
        const auto messages_per_second = utc == std::time(nullptr) ? pre_second_num : 0;
        ret.append({"messages_per_second", messages_per_second});
        ret.append({"messages_total", total_num});
        return ret;
    }
    Statistic_Data() = default;
};
class DF_Statistic_Data {
public:
    time_t utc{};
    size_t pre_second_num{};
    size_t total_num{};
    size_t crc_error_num{};
    Psc::JSON to_json() {
        std::lock_guard lock(mtx);
        return to_json_locked();
    }
    [[nodiscard]] std::tuple<size_t, size_t, size_t> counters() const {
        std::lock_guard lock(mtx);
        return {utc == std::time(nullptr) ? pre_second_num : 0, total_num, crc_error_num};
    }
    void add() {
        std::lock_guard lock(mtx);
        add_inter();
    }
    void add_crc_error() {
        std::lock_guard lock(mtx);
        crc_error_num++;
    }
    void add_sub_part(std::string_view key) {
        std::lock_guard lock(mtx);
        add_sub_part_inter(key);
    }
protected:
    Psc::JSON to_json_locked() const {
        Psc::JSON ret = Psc::JSON::object();
        const auto messages_per_second = utc == std::time(nullptr) ? pre_second_num : 0;
        const auto crc_error_percent = total_num == 0 ? 0.0 : static_cast<double>(crc_error_num) * 100.0 / static_cast<double>(total_num);
        ret.append({"messages_per_second", messages_per_second});
        ret.append({"messages_total", total_num});
        ret.append({"crc_errors_total", crc_error_num});
        ret.append({"crc_error_percent", crc_error_percent});
        Psc::JSON subtypes = Psc::JSON::object();
        for (const auto& cur : statistic_map) {
            subtypes.append({cur.first, cur.second.to_json()});
        }
        ret.append({"subtypes", subtypes});
        return ret;
    }
    void add_inter() {
        total_num++;
        auto cur_time = std::time(nullptr);
        if (cur_time != utc) {
            utc = cur_time;
            pre_second_num = 0;
        }
        pre_second_num++;
    }
    void add_sub_part_inter(std::string_view key) {
        auto t = get_create_statistic_data(key);
        t->total_num++;
        auto cur_time = std::time(nullptr);
        if (cur_time != t->utc) {
            t->utc = cur_time;
            t->pre_second_num = 0;
        }
        t->pre_second_num++;
    }
    Statistic_Data* get_create_statistic_data(std::string_view key) {
        Statistic_Data* t;
        auto key_string = std::string(key);
        auto iter = statistic_map.find(key_string);
        if (iter == statistic_map.end()) {
            Statistic_Data cur{};
            statistic_map.insert(std::make_pair(key_string, cur));
        }
        t = &statistic_map[key_string];
        return t;
    }
    std::map<std::string, Statistic_Data> statistic_map;
    mutable std::mutex mtx;
};
class CPR_Percentage_Statistic_Data {
public:
    void add(SSR::CPR_Type cpr_type, SSR::CPR_Ret_Type result_type) {
        std::lock_guard lock(mtx);
        switch (result_type) {
        case SSR::CPR_Ret_Type::Speed_Error:
        case SSR::CPR_Ret_Type::Parse_OK:
        case SSR::CPR_Ret_Type::Inter_Error:
        case SSR::CPR_Ret_Type::Time_Space_Too_Long:
            break;
        case SSR::CPR_Ret_Type::Lack_Other_Msg:
        case SSR::CPR_Ret_Type::Lack_Old_Pos:
        case SSR::CPR_Ret_Type::Base:
            return;
        }
        auto& statistic = statistic_map[cpr_type];
        ++statistic.total_num;
        ++statistic.result_num[result_type];
    }
    Psc::JSON to_json() const {
        std::lock_guard lock(mtx);
        Psc::JSON result = Psc::JSON::object();
        for (const auto& [cpr_type, statistic] : statistic_map) {
            Psc::JSON type_result = Psc::JSON::object();
            type_result.append({"total", statistic.total_num});
            for (auto result_type : statistic_types) {
                size_t num = 0;
                auto iter = statistic.result_num.find(result_type);
                if (iter != statistic.result_num.end()) {
                    num = iter->second;
                }
                double rate = statistic.total_num == 0 ? 0.0 : static_cast<double>(num) / static_cast<double>(statistic.total_num) * 100.0;
                Psc::JSON value = Psc::JSON::object();
                value.append({"count", num});
                value.append({"percent", rate});
                type_result.append({Psc::to_string(result_type), value});
            }
            result.append({Psc::to_string(cpr_type), type_result});
        }
        return result;
    }
protected:
    struct Statistic_Data {
        size_t total_num{};
        std::map<SSR::CPR_Ret_Type, size_t> result_num;
    };
    inline static constexpr std::array statistic_types{
    SSR::CPR_Ret_Type::Speed_Error, SSR::CPR_Ret_Type::Parse_OK, SSR::CPR_Ret_Type::Inter_Error,
    SSR::CPR_Ret_Type::Time_Space_Too_Long, SSR::CPR_Ret_Type::Out_of_Maximum_Detection_Range};
    std::map<SSR::CPR_Type, Statistic_Data> statistic_map;
    mutable std::mutex mtx;
};
class Mode_S_Statistic_Data {
public:
    Psc::JSON to_json() {
        std::lock_guard lock(mtx);
        size_t total_pre_second_num = 0;
        size_t total_num = 0;
        size_t crc_error_num = 0;
        for (auto& [_, statistic] : DF_Statistic_Data_map) {
            const auto [pre_second, total, crc_error] = statistic.counters();
            total_pre_second_num += pre_second;
            total_num += total;
            crc_error_num += crc_error;
        }
        Psc::JSON ret = Psc::JSON::object();
        const auto crc_error_percent = total_num == 0 ? 0.0 : static_cast<double>(crc_error_num) * 100.0 / static_cast<double>(total_num);
        ret.append({"messages_per_second", total_pre_second_num});
        ret.append({"messages_total", total_num});
        ret.append({"length_errors_total", length_error_num.load()});
        ret.append({"crc_errors_total", crc_error_num});
        ret.append({"crc_error_percent", crc_error_percent});
        Psc::JSON df_sub_type = Psc::JSON::object();
        for (auto& cur : DF_Statistic_Data_map) {
            df_sub_type.append({Psc::to_string(cur.first) + " [" + std::to_string(static_cast<int>(cur.first)) + "]",
                                cur.second.to_json()});
        }
        ret.append({"downlink_formats", df_sub_type});
        ret.append({"cpr", cpr_statistic_data.to_json()});
        return ret;
    }
    void add_length_error(std::string_view key) {
        ++length_error_num;
    }
    void add_cpr_error(SSR::CPR_Type cpr_type, SSR::CPR_Ret_Type result_type) {
        cpr_statistic_data.add(cpr_type, result_type);
    }
    DF_Statistic_Data* get_create_df_statistic_data(const SSR::Downlink_Format& key) {
        std::lock_guard lock(mtx);
        return &DF_Statistic_Data_map.try_emplace(key).first->second;
    }
    size_t get_total_pre_second_num() {
        std::lock_guard lock(mtx);
        size_t ret = 0;
        for (auto& cur : DF_Statistic_Data_map)
            ret += std::get<0>(cur.second.counters());
        return ret;
    }
    size_t get_total_num() {
        std::lock_guard lock(mtx);
        size_t ret = 0;
        for (auto& cur : DF_Statistic_Data_map)
            ret += std::get<1>(cur.second.counters());
        return ret;
    }
    size_t get_crc_error_num() {
        std::lock_guard lock(mtx);
        size_t ret = 0;
        for (auto& cur : DF_Statistic_Data_map)
            ret += std::get<2>(cur.second.counters());
        return ret;
    }
protected:
    std::atomic<size_t> length_error_num{};
    std::map<SSR::Downlink_Format, DF_Statistic_Data> DF_Statistic_Data_map;
    CPR_Percentage_Statistic_Data cpr_statistic_data;
    std::mutex mtx;
};
template <typename T>
class Immutable : public T {};
#endif
