/**
 * @file    dc_internal.h
 * @brief   数据中心内部共享声明（C++，仅模块内可见）
 * @note    对齐 RTU 原工程 dc_signal_internal.h 的架构
 */
#ifndef DC_INTERNAL_H
#define DC_INTERNAL_H

#include "myDatacenter.h"
#include "myBase.h"
#include "myLog.h"
#include "xxhash.h"

#include <string>
#include <vector>
#include <unordered_map>
#include <unordered_set>
#include <mutex>
#include <cstring>
#include <algorithm>

/* ================================================================
 * XXH128 哈希函数对象（与 RTU 原工程完全一致）
 * ================================================================ */
struct DCXXH128Hash
{
    size_t operator()(const XXH128_hash_t &h) const noexcept
    {
        const uint64_t mix1 = h.low64 ^ (h.high64 << 17);
        const uint64_t mix2 = mix1 + (h.high64 >> 13);
        const uint64_t mix3 = mix2 ^ (h.low64 << 23);

        return static_cast<size_t>(mix3 ^ (mix3 >> 32));
    }
};

struct DCXXH128Equal
{
    bool operator()(const XXH128_hash_t &a, const XXH128_hash_t &b) const noexcept
    {
        return (a.high64 == b.high64) && (a.low64 == b.low64);
    }
};

typedef std::unordered_multimap<XXH128_hash_t, dc_signal_t,
                                 DCXXH128Hash, DCXXH128Equal> dc_hash_map_t;

/* ================================================================
 * 信号存储容器
 * ================================================================ */
typedef struct
{
    std::mutex          mtx;
    uint32_t            signal_id;
    dc_hash_map_t       map_signals;
    std::vector<dc_signal_t *> id_index;
} dc_signal_map_t;

/* ================================================================
 * 异步请求结构体
 * ================================================================ */
typedef struct dc_async_request
{
    uint32_t request_id;
    char     saddr[DC_SADDR_MAX_LEN];
    dc_ctrl_step_t step;
    uint8_t  data_type;
    uint8_t  setting_zone;
    uint8_t  ctrl_type;
    uint8_t  signal_type;       /* 0=yk, 1=ao, 2=param */

    void *p_select_data;
    void *p_direct_data;

    uint64_t start_time_ms;
    uint32_t timeout_ms;

    char     caller_module[DC_MODULE_MAX_LEN];
    dc_async_result_cb_t result_cb;
    void    *user_arg;

    dc_async_exec_cb_t exec_cb;
    void    *module_ctx;

    int      result_code;
    char     err_msg[DC_ERR_MSG_MAX_LEN];

    struct dc_async_request *next;
} dc_async_request_t;

/* ================================================================
 * 异步请求队列
 * ================================================================ */
typedef struct
{
    std::mutex mtx;
    uint32_t   next_id;
    dc_async_request_t *head;
    int        count;
    int        max_pending;
    uint32_t   default_timeout_ms;
    uint32_t   default_timeout_yk_ms;
    uint32_t   default_timeout_ao_ms;
    uint32_t   default_timeout_param_ms;
    std::unordered_map<uint32_t, dc_async_request_t *> req_map;
} dc_async_queue_t;

/* ================================================================
 * 全局变量声明
 * ================================================================ */
extern dc_signal_map_t g_dc_out;
extern dc_signal_map_t g_dc_yk;
extern dc_signal_map_t g_dc_ao;
extern dc_signal_map_t g_dc_param;

extern std::vector<dc_signal_t *> g_dirty_out_signals;
extern std::mutex       g_dirty_out_mutex;

extern dc_async_queue_t g_async_queue;

extern bool             g_param_cfg_changed;
extern std::mutex       g_param_cfg_mutex;

extern char             g_cfg_dir[256];
extern bool             g_initialized;

extern std::unordered_map<std::string, dc_param_meta_t> g_param_metadata;

/* ================================================================
 * 跨文件函数声明
 * ================================================================ */

/* dc_core.cpp */
int          dc_core_add(dc_signal_t &signal, dc_signal_map_t &smap);
dc_signal_t *dc_core_find(const char *saddr, dc_signal_map_t &smap);
dc_signal_t *dc_core_find_out(const char *saddr);
dc_signal_t *dc_core_find_by_id(uint32_t id, dc_signal_map_t &smap);
void         dc_core_mark_dirty(dc_signal_t *p_signal);

/* dc_signal_util.cpp */
int          dc_util_val_compare(uint8_t data_type, const void *p1, const void *p2);
void         dc_util_val_copy(void *dst, const void *src, uint8_t data_type);
void        *dc_util_create_data(uint8_t data_type);
void         dc_util_destroy_data(void *p_data, uint8_t data_type);
std::string  dc_util_val_to_string(const void *p_data, uint8_t data_type);
int          dc_util_val_from_string(void *p_data, uint8_t data_type, const std::string &str);
std::string  dc_util_type_name(uint8_t data_type);
void         dc_internal_type_name(uint8_t dt, char *buf, int buf_len);
uint8_t      dc_util_type_id_by_name(const std::string &name);
uint8_t      dc_util_type_len(uint8_t data_type);

/* dc_signal_check.cpp */
int dc_check_ctrl_val_valid(const dc_ctrl_t *ctrl, const void *p_data);
int dc_check_ctrl_valid(const dc_signal_t *p_signal, dc_ctrl_step_t step,
                         dc_ctrl_t *ctrl, const void *p_data);
int dc_check_val_valid(const dc_signal_t *p_signal, uint8_t setting_zone,
                        const void *p_data);
int dc_check_yk_val_valid(dc_signal_t *p_signal, void *p_data);

/* dc_event.cpp */
int  dc_disturb_dd_queue_push(void *p_dd);
int  dc_disturb_dd_register_queue_pop(dc_queue_pop_cb_t cb);
void dc_disturb_dd_queue_pop(void);
int  dc_event_queue_push(void *p_soe);
int  dc_event_register_queue_pop(dc_queue_pop_cb_t cb);
void dc_event_queue_pop(void);
int  dc_fault_queue_push(void *p_fault);
int  dc_fault_register_queue_pop(dc_queue_pop_cb_t cb);
void dc_fault_queue_pop(void);

/* dc_async.cpp */
uint32_t dc_async_enqueue(dc_signal_map_t &smap, const char *saddr,
                           dc_ctrl_step_t step, const dc_ctrl_t *ctrl,
                           const void *p_data, uint8_t setting_zone,
                           uint8_t signal_type, const char *caller_module,
                           dc_async_result_cb_t result_cb, void *user_arg,
                           uint32_t timeout_ms);
int  dc_async_set_result(uint32_t request_id, int result_code, const char *err_msg);
int  dc_async_cancel(uint32_t request_id);
void dc_async_timeout_check(void);
void dc_async_cleanup(void);

/* dc_param_cfg.cpp */
int  dc_param_cfg_parse(const char *path);
void dc_param_metadata_store(const char *saddr, const dc_param_meta_t &param);
bool dc_param_metadata_lookup(const char *saddr, dc_param_meta_t &out_param);
void dc_param_cfg_check(const char *path);

#endif /* DC_INTERNAL_H */
