/*
 * @Author: zchuo zhengchen.huo@lnxall.com
 * @Date: 2025-05-26 09:49:37
 * @LastEditors: zchuo zhengchen.huo@lnxall.com
 * @LastEditTime: 2025-06-24 13:47:25
 * @FilePath: /proto_forward/src/accident/accident.h
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
 */
#ifndef __ACCIDENT_MODE_
#define __ACCIDENT_MODE_

#include "sqlite3.h"
#include <stdbool.h>  
#include <string.h>  
#include <stdlib.h>  
#include <ctype.h>  
#include <stdio.h>  

#include "../alarm_control/alarm_control.h"


#include <stdio.h>
#include "../mqtt_emms2/mqtt_emms2.h"
#if EN_TDENGINE
#include <tdengine/client/taos.h>
#include "../database/taos_database.h"

#endif
#include <openssl/md5.h>
#include <time.h>
#include "collector-api.h"


#define ACCIDENT_RULE_CONFIG_FILE "/app/config/emms2_accident_rule.json"
#define ACCIDENT_INFO_FILE_DIR   "/app/config"
#define ACCIDENT_RCV_FTP_TIMEOUT          600           // 接收ftp消息的超时时间
#define ACCIDENT_RCV_CLEAR_FILE_TIMEOUT   120           // 接收清除文件消息的超时时间
#define ACCIDENT_WAIT_CLEAR_FILE_TIMEOUT  600           // 等待清除文件消息的时间(超时就开始处理下一包)

#define ACCIDENT_ZIP_PATH "/mnt/ssd/accident"
#define ACCIDENT_DATA_TMP_PATH "/mnt/ssd/accident/tmp"

int time_granularity;  // min:1s  max:30s

enum ACCIDENT_CLOUD
{
    CLOUD_NON = 0,
    CLOUD_UP ,
    CLOUD_RUN ,
    CLOUD_DEL

};

enum ACCIDENT_PACK
{
    PACK_NON = 0,
    PACK_UP ,
    PACK_RUN ,
    PACK_END,
    PACK_ERR

};


struct Accident_dispose_t
{
// public:
    
    int code_id;            // 事故ID
    int front_time;         // 事故发生前时宽
    int after_time;         // 事故发生后时宽
    int pack_cnt;           // 事故打包次数，超过3次打包失败后，将取消打包资格 并反馈日志信息

// private: k
    time_t taos_timeid;     // taos数据记录在数据库时刻，做为唯一主键用以标识
    list_t Accident_queue;  // 事故列表
    time_t start_time;      // 事故数据记录 开始时刻时间 后续优化掉
    time_t Occurrence_time; // 事故触发时间
    time_t end_time;        // 事故数据记录 结束时刻时间

/*此设计以便于支持异步操作*/
    enum ACCIDENT_PACK pack;    // 打包使能 4:打包失败需要手动重置打包 0:暂未达到打包条件 1:需要打包 2: 打包中 3: 打包结束需上传
    enum ACCIDENT_CLOUD cloud;   // 上云使能 0:暂未达到上云条件 1:需要上云 2: 传输中 3: 删除并退队  
    char md5[MD5_DIGEST_LENGTH*2 + 2];   //
};
extern struct Accident_dispose_t *Accident_dispose;


struct Accident_data_info
{
    char *tagname;   // tag名称
    char tabname[64 + 32];   // 拼接号的taos表名称   但列表头用以记录设备no
    list_t list;
    #if EN_TDENGINE
    TAOS_RES *res;
    #else
    void *res;
    #endif

    int mode_type;      // -1:数据库中无此数据表 0:正常 1:无数据序列但前置时间内有数据执行全量覆盖写入 2:时间戳end之前数据表为空导致无法填充 覆写NULL
    double value;       // mode_type = 2 时存入的数据
};

typedef struct accident_info_t
{
    uint32_t alarm_code;     // 告警编码
    int time[2];             // 时间范围(分钟)
}accident_info_t;

// 存储规则信息
typedef struct accident_rule_t
{
    int id;             // 规则ID
    int time[2];        // 时间范围(分钟)
    char *rule;         // 规则表达式字符串
    char *name;         // 规则名
} accident_rule_t;

typedef struct alarm_event_t
{
    uint32_t           alarm_code;              // 告警编码
    list_head_t        list;
} alarm_event_t;

typedef struct accident_control_t
{
    accident_rule_t* accident_rule;
    int              accident_rule_count;

    // 实时告警事件链表
    list_head_t      alarm_event_list;
    pthread_mutex_t  alarm_event_list_mutex;
    int              alarm_event_list_size;
    int              alarm_event_list_max_size;

} accident_control_t;

typedef enum 
{ 
    TOKEN_NUM, 
    TOKEN_AND, 
    TOKEN_OR, 
    TOKEN_LPAREN, 
    TOKEN_RPAREN, 
    TOKEN_EOF 
} TokenType;

typedef struct 
{
    TokenType type;
    uint32_t value; // 仅TOKEN_NUM有效
} Token;

// 事故文件上传状态
typedef enum 
{
    ACCIDENT_STATE_INIT,           // 初始状态
    ACCIDENT_STATE_WAITING_FTP,    // 已发送MD5，等待FTP信息
    // ACCIDENT_STATE_UPLOADING,      // 正在上传文件
    ACCIDENT_STATE_WAITING_CLEAR,  // 文件已上传，等待清除指令
    // ACCIDENT_STATE_COMPLETED       // 完成（待清除文件）
} Accident_Upload_State_t;

// 事故文件上传时间记录
typedef struct
{
    time_t send_md5_time;
    time_t rcv_ftp_time;
    time_t send_file_time;
    time_t rcv_clear_file_time;
} Accident_Upload_Time_t;

// 事故文件上传控制信息
typedef struct 
{
    Accident_Upload_State_t  accident_upload_state;
    Accident_Upload_Time_t   accident_upload_time;
    bool                     send_accident_create_upload_flag;    // 事故反演历史数据上报标志 true为发送，false为不发送
    bool                     rcv_accident_clear_flag;             // 接收事故反演清除文件标识 true为收到，false为没收到
    // char send_md5[MD5_DIGEST_LENGTH + 2];                         // 发送的md5信息
    // char rcv_md5[MD5_DIGEST_LENGTH + 2];                          // 接收的md5信息
    char send_md5[34];                         // 发送的md5信息
    char rcv_md5[34];                          // 接收的md5信息
} Accident_Upload_Control_t;

extern accident_control_t accident_control;
extern struct Accident_dispose_t *clould_info;
extern Accident_Upload_Control_t accident_upload_control;
// 初始化事故控制模块 入口
int init_accident_control_task(void);
int accident_control_destory(accident_control_t* accident_control);

// 外部操作API
int accident_record_api(int code_id, int front_time, int after_time);
int accident_del_api(char *md5);
struct Accident_dispose_t * accident_get_clould_api();
int accident_cloud_df_api(struct Accident_dispose_t * tmp);

// 队列操作
alarm_event_t* create_alarm_event_node(alarm_real_t *real);
int push_alarm_event_to_queue(alarm_event_t* alarm_event);
alarm_event_t* peek_alarm_event_from_queue(void);
alarm_event_t* pop_alarm_event_from_queue(void);

// 事故配置json文件处理
int deal_accident_rule_config(cJSON *root);
int save_accident_rule_config_file(cJSON *root);

// 事故文件上传
void update_accident_send_md5_time(void);
void update_accident_send_file_time(void);
int deal_accident_upload_info(mqtt_emms2_var_t *var, cJSON *root);
int deal_accident_clear(cJSON *root);
int accident_info_report(mqtt_emms2_var_t* var, char* function, char* file_md5);
int start_accident_upload_task(void);

int accident_dispose_init();
int accident_data_list_init();

int str_time_get(time_t time_now, char *buf); // 将time_t转换为"年-月-日 时:分:秒"格式
int str_time_parse(const char *time_str, time_t *time_out); // 将"年-月-日 时:分:秒"格式字符串转换为time_t
int accident_Init();

#endif