#ifndef ASYNC_LOGGER_H
#define ASYNC_LOGGER_H

// 定义 _WIN32_WINNT 以支持 Windows 10/11 API（0x0A00 表示 Windows 10/11）
#ifndef _WIN32_WINNT
#define _WIN32_WINNT 0x0A00
#endif

#include <spdlog/spdlog.h>
#include <spdlog/async.h>                      // 异步日志支持
#include <spdlog/sinks/stdout_color_sinks.h>     // 控制台彩色输出
#include <spdlog/sinks/rotating_file_sink.h>     // 滚动文件输出
#include <memory>
#include <chrono>
#include <vector>

// --------------------------------------------------------------------
// 自定义阈值过滤器 sink：包装另一个 sink，仅当消息级别 >= threshold 时转发日志
#include <spdlog/sinks/sink.h>

namespace spdlog::sinks {

template<typename Mutex>
class threshold_filter_sink : public sink {
public:
    threshold_filter_sink(std::shared_ptr<sink> wrapped_sink, spdlog::level::level_enum threshold)
        : wrapped_sink_(std::move(wrapped_sink)), threshold_(threshold) {}

    void log(const spdlog::details::log_msg &msg) override {
        if (msg.level >= threshold_) {
            wrapped_sink_->log(msg);
        }
    }

    void flush() override {
        wrapped_sink_->flush();
    }

    void set_pattern(const std::string &pattern) override {
        wrapped_sink_->set_pattern(pattern);
    }

    void set_formatter(std::unique_ptr<spdlog::formatter> sink_formatter) override {
        wrapped_sink_->set_formatter(std::move(sink_formatter));
    }

private:
    std::shared_ptr<sink> wrapped_sink_;
    spdlog::level::level_enum threshold_;
};

} // namespace spdlog::sinks

// --------------------------------------------------------------------

// --------------------------------------------------------------------
// 为 Boost 类型提供自定义格式化器（示例：仅提供 boost::asio::ip::basic_endpoint 格式化支持）
#include <boost/asio/ip/basic_endpoint.hpp>
#include <boost/asio/ip/address.hpp>
namespace fmt {
    template<typename Protocol>
    struct formatter<boost::asio::ip::basic_endpoint<Protocol>> {
        constexpr auto parse(format_parse_context &ctx) { return ctx.begin(); }
        template<typename FormatContext>
        auto format(const boost::asio::ip::basic_endpoint<Protocol> &ep, FormatContext &ctx) {
            return format_to(ctx.out(), "{}:{}", ep.address().to_string(), ep.port());
        }
    };
}
// --------------------------------------------------------------------

// 配置是否采用溢出丢弃策略（默认为阻塞策略）
//#define ENABLE_ASYNC_OVERFLOW_OVERRUN

namespace logger {

// 使用全局静态线程池，确保其生命周期与日志器一致
inline std::shared_ptr<spdlog::details::thread_pool> thread_pool;

// 定义编译时常量日志格式，与 log4j2 类似
constexpr const char *console_pattern = "%Y-%m-%d %H:%M:%S.%e [%-5l] [%t] %n - %v";
constexpr const char *file_pattern    = "%Y-%m-%d %H:%M:%S.%e [%-5l] [%t] %n - %v";

// 初始化异步日志模块
inline void init_async_logger() {
    // 日志文件路径及滚动参数
    const std::string log_home = "../logs/game";
    const std::string general_log_file = log_home + "/log.log";
    const std::string error_log_file   = log_home + "/error.log";
    // 最大文件大小 250 MB，最多保留 240 个文件
    size_t max_size = 250 * 1024 * 1024;
    size_t max_files = 240;

    // 创建线程池：队列大小 8192，线程数 1
    thread_pool = std::make_shared<spdlog::details::thread_pool>(8192, 1);

    // 创建控制台 sink
    auto console_sink = std::make_shared<spdlog::sinks::stdout_color_sink_mt>();
    console_sink->set_pattern(console_pattern);

    // 创建普通日志文件 sink（滚动文件方式）
    auto file_sink = std::make_shared<spdlog::sinks::rotating_file_sink_mt>(general_log_file, max_size, max_files);
    file_sink->set_pattern(file_pattern);

    // 创建错误日志文件 sink（滚动文件方式）
    auto error_file_sink_raw = std::make_shared<spdlog::sinks::rotating_file_sink_mt>(error_log_file, max_size, max_files);
    error_file_sink_raw->set_pattern(file_pattern);
    // 使用阈值过滤器包装，仅记录 ERROR 及以上级别日志
    auto error_file_sink = std::make_shared<spdlog::sinks::threshold_filter_sink<std::mutex>>(error_file_sink_raw, spdlog::level::err);

    // 汇总所有 sink
    std::vector<spdlog::sink_ptr> sinks { console_sink, file_sink, error_file_sink };

#ifdef ENABLE_ASYNC_OVERFLOW_OVERRUN
    constexpr auto overflow_policy = spdlog::async_overflow_policy::overrun;
#else
    constexpr auto overflow_policy = spdlog::async_overflow_policy::block;
#endif

    // 创建异步 logger，名称设为 "logger"
    auto async_logger = std::make_shared<spdlog::async_logger>(
        "",
        sinks.begin(), sinks.end(),
        thread_pool,
        overflow_policy
    );

    // 设置为默认 logger，设置全局日志级别为 DEBUG（文件输出用 DEBUG 级别，控制台同理，可根据需要调整）
    spdlog::set_default_logger(async_logger);
    spdlog::set_level(spdlog::level::debug);
    // 针对错误日志，可以设置 flush_on(ERROR) 保证立即刷新
    spdlog::flush_on(spdlog::level::err);
    // 定时刷新所有日志（例如每 3 秒刷新一次）
    spdlog::flush_every(std::chrono::seconds(3));

    spdlog::info("Async logger initialized (Console, Rotating File, Error Filter).");
}

// 在程序退出前调用，确保日志系统干净关闭
inline void shutdown_logger() {
    spdlog::shutdown();
    thread_pool.reset();
}

} // namespace logger

#endif // ASYNC_LOGGER_H
