#include "Global.h"
#include <drogon/HttpAppFramework.h>
#include <filesystem>
#include <sstream>
#include <string>
#include <string_view>
BaseLogger* server_logger = nullptr;
Debug_Logger_Info_Manager debug_logger_info_manager;
void Global::handle_old_logs() {
    auto mode = log_config.open_mode;
    std::string dirPath = get_exe_dir() + "/" + "logs";
    namespace fs = std::filesystem;
    try {
        switch (mode) {
        case Log_Config::Open_Mode::Rename: {
            auto now = std::chrono::system_clock::now();
            auto in_time_t = std::chrono::system_clock::to_time_t(now);
            std::ostringstream oss;
            oss << std::put_time(std::localtime(&in_time_t), "%Y-%m-%d_%H-%M-%S");
            fs::path newDirPath = dirPath + "_" + oss.str();
            if (fs::exists(newDirPath)) {
                std::cout << "New directory name already exists!" << std::endl;
                return;
            }
            fs::rename(dirPath, newDirPath);
            std::cout << "Directory renamed to: " << newDirPath << std::endl;
            break;
        }
        case Log_Config::Open_Mode::Delete: {
            if (fs::exists(dirPath)) {
                fs::remove_all(dirPath); // 删除目录及其所有内容
                std::cout << "Directory and its contents deleted: " << dirPath << std::endl;
            }
            if (fs::create_directories(dirPath)) {
                std::cout << "Directory created: " << dirPath << std::endl;
            }
            else {
                std::cout << "创建目录失败: " << dirPath << std::endl;
                Psc::fail_fast();
            }
            fs::permissions(dirPath, fs::perms::owner_all | fs::perms::group_all | fs::perms::others_all);
            break;
        }
        case Log_Config::Open_Mode::Append:
            break;
        default:
            std::cerr << "未知的打开模式!" << std::endl;
            break;
        }
    }
    catch (const std::exception& ex) {
        std::cerr << "Error: " + Psc::platform_2_utf8(ex.what()) + "\n";
    }
}
Global::Global() {
    auto j = load();
    log_config.from_base_json(j.get("log"), false);
    handle_old_logs();
    Base_Logger_Manager::instance()->set_thread_num(1).set_flush_seconds(3).init();
    int piece_num = log_config.piece_num;
    int size_MB = log_config.size_MB;
    int MB = 1024 * 1024;
    asio_socket::socket_logger = new BaseLogger("@/logs/socket", MB * size_MB, piece_num);
    serial::serial_logger = new BaseLogger("@/logs/serial", MB * size_MB, piece_num);
    SSR::mode_s_logger = new BaseLogger("@/logs/mode_s", MB * size_MB * 10, piece_num);
    dsp_logger = new BaseLogger("@/logs/dsp", MB * size_MB, piece_num);
    server_logger = new BaseLogger("@/logs/server", MB * size_MB, piece_num);
    asio_socket::socket_logger->set_redirect([](const BaseLogger::Log_Info& log_info) {
        auto msg = "[" + std::string("func") + "~" + log_info.func_pattern + "] " + log_info.log_type.to_string() +
        log_info.content;
        debug_logger_info_manager.push_info(msg);
    });
    serial::serial_logger->set_redirect([](const BaseLogger::Log_Info& log_info) {
        auto msg = "[" + std::string("func") + "~" + log_info.func_pattern + "] " + log_info.log_type.to_string() +
        log_info.content;
        debug_logger_info_manager.push_info(msg);
    });
    from_base_json(&j, false);
#ifdef Cache_Some_Mode_S
    auto old_parse_ok_json = SSR::parse_ok_json;
    SSR::parse_ok_json = [old_parse_ok_json](Aircraft_Info* aircraft_info, SSR::P_S mode_s_msg, Psc::JSON json) {
        old_parse_ok_json(aircraft_info, mode_s_msg, json);
        auto f = static_cast<Aircraft*>(aircraft_info);
        f->add_msg_limit(mode_s_msg);
    };
#endif
    SSR::cpr_cb = [](SSR::CPR_Type t, SSR::CPR_Ret_Type err_type, std::string_view log, SSR::P_S msg) {
        auto src = std::dynamic_pointer_cast<Data_Source>(msg->source);
        Mode_S_Statistic_Data* ss = &src->mode_s_statistic;
        ss->add_cpr_error(t, err_type);
        SSR::mode_s_logger->debug("CPR/" + to_string(t) + "/" + to_string(err_type), {}, log);
    };
    // 处理错误
    SSR::parse_call_back = [this](SSR::Parse_Call_Back_Type type, SSR::Aircraft_Info* info, std::string_view field_name,
                                  std::vector<std::string> bds_list, void*, SSR::P_S msg) {
        auto src = std::dynamic_pointer_cast<Data_Source>(msg->source);
        Mode_S_Statistic_Data* ss = &src->mode_s_statistic;
        if (type == SSR::Parse_Call_Back_Type::Unknown_DF) {
            // std::cout << "Unknown DF type!" << (int)(msg->df) << std::endl;
            return;
        }
        DF_Statistic_Data* dfs = ss->get_create_df_statistic_data(msg->df);
        dfs->add();
        if (type == SSR::Parse_Call_Back_Type::Normal_Block) {
            dfs->add_sub_part(field_name);
            info->update(msg);
        }
        else if (type == SSR::Parse_Call_Back_Type::CRC_Error) {
            dfs->add_crc_error();
            // std::cout << field_name <<  " :crc_error msg:" << msg->msg_hex <<
            // "  df:" << (int)msg->df << std::endl;
        }
        else if (type == SSR::Parse_Call_Back_Type::Length_Error) {
            ss->add_length_error(field_name);
            // std::cout << field_name <<  " :length_error msg:" << msg->msg_hex
            // <<  "  df:" << (int)msg->df << std::endl;
        }
        // else if (type == Mode_S::Parse_Call_Back_Type::UNKNOWN_ERROR) {} else
        // {}
    };
    auto str = toJson().to_json_string();
    server_logger->debug("启动", {}, str);
    SSR::mode_s_logger->debug("启动", {}, str);
    std::cout << str << std::endl;
    init_web_server();
}
Global::~Global() {
    std::cout << "Global::~Global()" << std::endl;
}
void Debug_Logger_Info_Manager::push_info(std::string_view c) {
    std::lock_guard g(mtx);
    std::string content = std::to_string(cur_serial_number) + ": " + std::string(c);
    size_t content_length = content.size();
    info_list.push_back({cur_serial_number, content});
    current_total_length += content_length;
    while (current_total_length > max_length && !info_list.empty()) {
        current_total_length -= info_list.front().content.size();
        info_list.pop_front(); // 删除最早的记录
    }
    cur_serial_number++;
}
Serial_Number_Type Debug_Logger_Info_Manager::get_cur_serial_number() {
    std::lock_guard g(mtx);
    return cur_serial_number;
}
JSON Debug_Logger_Info_Manager::to_json() {
    JSON ret = JSON::object();
    ret.append({"cur_serial_number", cur_serial_number});
    return ret;
}
bool Web_Server::listen(std::string_view host, int port) {
    drogon::HttpAppFramework* app = &drogon::app();
    auto g = Global::instance();
    Json::Value drogon_config;
    {
        auto jsonStr = g->drogon_config.to_json_string();
        std::cout << "drogon::app().run();  " << jsonStr << std::endl;
        Json::CharReaderBuilder builder;
        std::string errs;
        auto reader = builder.newCharReader();
        if (!reader->parse(jsonStr.c_str(), jsonStr.c_str() + jsonStr.size(), &drogon_config, &errs)) {
            // 解析失败
            std::cout << "drogon 配置文件加载失败！json格式解析失败！" << jsonStr << std::endl;
            Psc::fail_fast();
        }
        delete reader;
    }
    app->loadConfigJson(drogon_config);
    app->disableSigtermHandling(); // 关闭服务器信号处理
    app->addListener(std::string(host), port);
    auto base_dir = get_exe_dir();
    // app->setLogPath(base_dir + "/logs/drogon.log");
    app->setUploadPath(base_dir + "/../drogon_uploads");
    app->run();
    return true;
}
Web_Server& Web_Server::Post(std::string_view pattern, Handler handler) {
    drogon::app().registerHandler(
    std::string(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& Web_Server::Post_Coro(std::string_view pattern, CoroHandler handler) {
    drogon::app().registerHandler(
    std::string(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());
                std::terminate();
            }
            catch (...) {
                resp->setStatusCode(drogon::k500InternalServerError);
                resp->setBody(Psc::JSON::object({{"error", "unknown error"}}).to_json_string());
                std::terminate();
            }
            callback(resp);
            co_return;
        });
    },
    {drogon::Post});
    return *this;
}
Web_Server& Web_Server::Get(std::string_view pattern, Handler handler) {
    drogon::app().registerHandlerViaRegex(
    std::string(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;
}
std::string Debug_Logger_Info_Manager::get_info(Serial_Number_Type serial_number) {
    std::lock_guard g(mtx);
    std::string result;
    if (serial_number == cur_serial_number) {
        return "";
    }
    // 从后向前遍历 data 列表
    for (auto it = info_list.rbegin(); it != info_list.rend(); ++it) {
        // std::cout << "max_length: " << max_length << "  size: " <<
        // info_list.size() << " serial_number " << serial_number  << "cur_sequence"
        // << it->sequence << "  content.size" << it->content.size() << std::endl;
        if (it->sequence >= serial_number) {
            result = it->content + result; // 叠加 content
        }
        else {
            break;
        }
    }
    return result;
}
std::string inet_address_to_string(const trantor::InetAddress& addr) {
    char buf[INET6_ADDRSTRLEN] = {0};
    if (!addr.isIpV6()) {
        // IPv4
        auto sa = reinterpret_cast<const struct sockaddr_in*>(addr.getSockAddr());
        inet_ntop(AF_INET, &(sa->sin_addr), buf, sizeof(buf));
        uint16_t port = ntohs(sa->sin_port);
        return std::string(buf) + ":" + std::to_string(port);
    }
    else {
        // IPv6
        auto sa6 = reinterpret_cast<const struct sockaddr_in6*>(addr.getSockAddr());
        inet_ntop(AF_INET6, &(sa6->sin6_addr), buf, sizeof(buf));
        uint16_t port = ntohs(sa6->sin6_port);
        return "[" + std::string(buf) + "]:" + std::to_string(port);
    }
}
