#ifndef LOG4_H
#define LOG4_H

#ifdef __cplusplus

#include <log4cplus/mdc.h>   // ★新增：需要 MDCGuard

#include <string>
#include <map>

//防止#include <log4cplus/logger.h>里的冲突
#ifdef min
#undef min
#endif

#ifdef max
#undef max
#endif
//防止#include <log4cplus/logger.h>里的冲突

#include "logger.h"
#include <set>
#include "loggingmacros.h"

#include "appender.h"

struct TypedLogger {
    log4cplus::Logger logger;
    int code;
    TypedLogger();
    TypedLogger(const log4cplus::Logger& l, int t);
};

struct DebugSwitch {
    bool debug_open;
    std::set<std::string> targets;
    int min_level;
    std::map<int, bool> type_enable;

    DebugSwitch();
    void open();
    void close();
    void set_target(const std::string& name);
    void set_level(int level);
    void enable_type(int type);
    void disable_type(int type);
    bool match(const std::string& logger_name, int level, int code);
};

extern std::map<std::string, TypedLogger> logger_map;
extern DebugSwitch g_debug_switch;

extern void send_reply_to_kafka(const std::string& guid, const std::string& step, const std::string& result);
extern void send_reply_to_kafka_recall(const std::string& guid, const std::string& step, const std::string& result,const std::string& lineIndex,const std::string& recallStartDate,const std::string& recallEndDate);


std::string get_front_type_from_subdir();


// 不带 Appender 的版本
log4cplus::Logger init_logger(const std::string& full_name,
                              const std::string& file_dir,
                              const std::string& base_file);

// 带 Appender 的版本
log4cplus::Logger init_logger(const std::string& full_name,
                              const std::string& file_dir,
                              const std::string& base_file,
                              log4cplus::SharedAppenderPtr fileAppender);

void process_log_command(const std::string& id, const std::string& level, const std::string& grade, int code);


void update_log_entries_countdown();

/////////////////////////////////////////////////////////////////////lnk20260306数据追踪
void process_trace_command(const std::string& id, int times);

extern "C" {
#endif
void remove_loggers_by_terminal_id(const char* terminal_id_cstr);
void init_logger_process();
void init_loggers();
void init_loggers_bydevid(const char* dev_id);

void log_debug(const char* key, const char* msg);
void log_info(const char* key, const char* msg);
void log_warn(const char* key, const char* msg);
void log_error(const char* key, const char* msg);

void send_reply_to_kafka_c(const char* guid, const char* step, const char* result);
void send_reply_to_kafka_recall_c(const char* guid, const char* step, const char* result,const char* lineIndex,const char* recallStartDate,const char* recallEndDate);
void format_log_msg(char* buf, size_t buf_size, const char* fmt, ...);

// ====================== ★新增：线程局部变量透传 code ======================
// 说明：使用编译器的 TLS（__thread）保存当前日志的 code 值。
//      在每次打日志前写入，打完后恢复，Appender 读取该值写入 JSON。
#if defined(__GNUC__)
  #define LOG_TLS __thread
#else
  // 若编译器不支持 __thread，可替换为 C++11 thread_local（但你的工程多为 C++98/C 混编，优先 __thread）
  #define LOG_TLS __thread
#endif

extern LOG_TLS int g_log_code_tls;  // 声明为 TLS 变量，定义见 log4.cpp
// ====================== ★新增结束 ======================


// ====================== 日志宏区域 ======================

#define DIY_LOG_CODE(LEVEL_FUNC, KEY, KEY_TYPE, CODE_INT, ...)               \
    do {                                                                     \
        int __old_code__ = g_log_code_tls;                                   \
        g_log_code_tls = (int)(CODE_INT);                                    \
                                                                             \
        char __msg_buf__[512];                                               \
        format_log_msg(__msg_buf__, sizeof(__msg_buf__), __VA_ARGS__);       \
                                                                             \
        const char* __key_raw__ = (KEY);                                     \
                                                                             \
        char __key_buf__[512];                                               \
        switch ((int)(KEY_TYPE)) {                                           \
            case 0:                                                          \
                snprintf(__key_buf__, sizeof(__key_buf__), "process");       \
                break;                                                       \
            case 1:                                                          \
                snprintf(__key_buf__, sizeof(__key_buf__),                   \
                         "terminal.%s", __key_raw__);                        \
                break;                                                       \
            case 2:                                                          \
                snprintf(__key_buf__, sizeof(__key_buf__),                   \
                         "monitor.%s", __key_raw__);                         \
                break;                                                       \
            default:                                                         \
                snprintf(__key_buf__, sizeof(__key_buf__), "%s",             \
                         __key_raw__);                                       \
                break;                                                       \
        }                                                                    \
                                                                             \
        LEVEL_FUNC(__key_buf__, __msg_buf__);                                \
        g_log_code_tls = __old_code__;                                       \
    } while (0)

// ★修改：默认宏改为 code=0（兼容原有用法）
#define DIY_ERRORLOG(KEY, ...) DIY_LOG_CODE(log_error, KEY, 0, LOG_CODE_OTHER,__VA_ARGS__)   // ★修改：默认 code=0
#define DIY_WARNLOG(KEY,  ...) DIY_LOG_CODE(log_warn,  KEY, 0, LOG_CODE_OTHER,__VA_ARGS__)   // ★修改：默认 code=0
#define DIY_INFOLOG(KEY,  ...) DIY_LOG_CODE(log_info,  KEY, 0, LOG_CODE_OTHER,__VA_ARGS__)   // ★修改：默认 code=0
#define DIY_DEBUGLOG(KEY, ...) DIY_LOG_CODE(log_debug, KEY, 0, LOG_CODE_OTHER,__VA_ARGS__)   // ★修改：默认 code=0

// ★新增：显式传入 code 的便捷宏
#define DIY_ERRORLOG_CODE(KEY, LEVEL_INT,CODE_INT, ...) DIY_LOG_CODE(log_error, KEY, LEVEL_INT, CODE_INT, __VA_ARGS__)  // ★新增
#define DIY_WARNLOG_CODE(KEY,  LEVEL_INT,CODE_INT, ...) DIY_LOG_CODE(log_warn,  KEY, LEVEL_INT, CODE_INT, __VA_ARGS__)  // ★新增
#define DIY_INFOLOG_CODE(KEY,  LEVEL_INT,CODE_INT, ...) DIY_LOG_CODE(log_info,  KEY, LEVEL_INT, CODE_INT, __VA_ARGS__)  // ★新增
#define DIY_DEBUGLOG_CODE(KEY, LEVEL_INT,CODE_INT, ...) DIY_LOG_CODE(log_debug, KEY, LEVEL_INT, CODE_INT, __VA_ARGS__)  // ★新增


// ====================== 日志宏区域 ======================


typedef enum LogCode {
    LOG_CODE_MENU_CONTROL     = 94,    /* 目录控制类型 */
    LOG_CODE_FILE_CONTROL     = 95,    /* 文件控制类型 */
    LOG_CODE_WIRETYPE          = 96,    /* 接线类型 */
    LOG_CODE_CONFIG            = 97,    /* 配置相关 */
    LOG_CODE_JSON              = 98,    /* JSON结构 */
    LOG_CODE_OTHER             = 99,   /* 其他类型 */
    LOG_CODE_LEDGER            = 100,  /* 台账类型 */
    LOG_CODE_RPTINIT           = 101,  /* 报告初始化 */
    LOG_CODE_ICD_AND_DOWNLOAD  = 200,  /* ICD 和文件下载类型 */
    LOG_CODE_TRANSIENT         = 300,  /* 暂态发生 */
    LOG_CODE_TRANSIENT_COMM    = 301,  /* 暂态接口 */
    LOG_CODE_COMTRADE_FILE     = 302,  /* 录波文件（Comtrade） */
    LOG_CODE_GGIO_LPHD         = 304,  /* GGIO事件 */
    LOG_CODE_MQ                = 400,  /* MQ发送 */
    LOG_CODE_RT_DATA           = 401,  /* 实时数据 */
    LOG_CODE_LEDGER_UPDATE     = 402,  /* 台账更新 */
    LOG_CODE_PROCESS_CONTROL   = 403,  /* 进程控制 */
    LOG_CODE_RECALL            = 404,  /* 补招相关 */
    LOG_CODE_LOG_REQUEST       = 405,  /* 日志请求 */
    LOG_CODE_REPORT            = 500,  /* 报告处理 */
    LOG_CODE_COMM              = 600,  /* 通讯状态 */
    LOG_CODE_SPACE_ALARM       = 700,   /* 空间告警 */
    LOG_CODE_DEVICE            = 800   /* 设备告警 */    
} LogCode;

#ifdef __cplusplus
}
#endif



#endif // LOG4_H
