#include "alarm_database.h"
#include "alarm_define.h"
#include "alarm_control.h"
#include <string.h>
#include <sys/syslog.h>
#include "../tag.h"
#include "../proto_forward.h"
#include "collector-api.h"
extern alarm_control_t alarm_control;

#ifdef EN_TDENGINE
#include "../database/taos_database.h"
int check_and_create_table(void* taos);
int init_alarm_db(void** db)
{
    *db = tdengine_connect(NULL, 0, NULL, NULL, NULL);
    if (*db == NULL)
    {
        ems_syslog(LOG_ERR, "tdengine connect failed");
        return -1;
    }

    char sql[1024] = {0};
    snprintf(sql, sizeof(sql), CREATE_ALARM_HISTORY_DB, ALARM_DB_NAME);
    TAOS_RES* res = taos_query(*db, sql);
    if (res == NULL)
    {
        ems_syslog(LOG_ERR, "create alarm history db failed");
        return -1;
    }
    if (taos_errno(res) != 0)
    {
        ems_syslog(LOG_ERR, "create alarm history db failed, err=%s", taos_errstr(res));

        taos_free_result(res);
        return -1;
    }
    snprintf(sql, sizeof(sql), "use %s", ALARM_DB_NAME);
    res = taos_query(*db, sql);
    if (res == NULL)
    {
        ems_syslog(LOG_ERR, "create alarm history db failed");
        return -1;
    }
    if (taos_errno(res) != 0)
    {
        ems_syslog(LOG_ERR, "create alarm history db failed, err=%s", taos_errstr(res));

        taos_free_result(res);
        return -1;
    }

    return check_and_create_table(*db);
}

int close_alarm_db(void** db)
{
    taos_cleanup();
    taos_close(*db);
    *db = NULL;
    return 0;
}

int create_alarm_table(void* db)
{
    TAOS_RES* res = taos_query(db, TDENGINE_CREATE_ALARM_TAB_SQL);
    if (res == NULL)
    {
        ems_syslog(LOG_ERR, "create alarm table failed");
        return -1;
    }
    if (taos_errno(res) != 0)
    {
        ems_syslog(LOG_ERR, "create alarm table failed, err=%s", taos_errstr(res));
        taos_free_result(res);
        return -1;
    }
    taos_free_result(res);
    return 0;
}

int check_alarm_table_num_columns(void* db)
{
    char sql[512] = {0};
    snprintf(sql, sizeof(sql), "DESCRIBE %s", ALARM_REAL_TAB);
    TAOS_RES* res = taos_query(db, sql);
    if (res == NULL || taos_errno(res) != 0)
    {
        ems_syslog(LOG_ERR, "Error in describe: %s\n", res ? taos_errstr(res) : "NULL");
        if (res) taos_free_result(res);
        return -1;
    }
    int num_columns = taos_affected_rows(res);
    taos_free_result(res);
    return num_columns;
}

int check_and_create_table(void* db)
{
    // 查询表的信息
    char sql[512] = {0};
    snprintf(sql, sizeof(sql), "SHOW TABLES LIKE '%s';", ALARM_REAL_TAB);
    TAOS_RES*   res  = taos_query(db, sql);
    if (res == NULL || taos_errno(res) != 0)
    {
        ems_syslog(LOG_ERR, "Error in query: %s\n", res ? taos_errstr(res) : "NULL");
        if(res) taos_free_result(res);
        return -1;
    }

    int num_fields = taos_num_fields(res);
    taos_free_result(res);

    if (num_fields == 0)
    {
        // 表不存在，创建表
        return create_alarm_table(db);
    }
    else
    {
        // 表存在，检查列数
        int num_columns = check_alarm_table_num_columns(db);
        if (num_columns != ALARM_REAL_TAB_NUM_COLUMN)
        {
            // 删除表
            snprintf(sql, sizeof(sql), "DROP TABLE %s", ALARM_REAL_TAB);
            res  = taos_query(db, sql);
            if (res == NULL || taos_errno(res) != 0)
            {
                ems_syslog(LOG_ERR, "Error dropping table: %s\n", res ? taos_errstr(res) : "NULL");
                taos_free_result(res);
            }
            // 重新创建表
            return create_alarm_table(db);
        }
    }
    return 0;
}
extern bool is_alarm(alarm_info_t* alarm_info, tag_t* alarm);
void get_all_real_alarm_from_db()
{
    if (alarm_control.db == NULL)
    {
        return;
    }
    TAOS_RES* res = taos_query(alarm_control.db, GET_ALARM_REAL_FROM_DB);
    if (res == NULL)
    {
        return;
    }
    if (taos_errno(res) != 0)
    {
        ems_syslog(LOG_ERR, "select alarm from taosd failed: %s", taos_errstr(res));
        goto ERR0;
    }

    int      alarm_code  = 0;
    int      reason_code = 0;
    TAOS_ROW row         = NULL;
    char     key[32]     = {0};
    int      key_len     = 0;

    while ((row = taos_fetch_row(res)) != NULL)
    {
        alarm_real_t* real = (alarm_real_t*)calloc(1, sizeof(alarm_real_t));
        if (real == NULL)
        {
            goto ERR0;
        }
        real->raise    = *(int64_t*)row[0];
        real->recovery = *(int64_t*)row[1];
        alarm_code     = *(int32_t*)row[2];
        reason_code    = *(int32_t*)row[3];
        real->status   = *(int8_t*)row[7];

        int charLen = *((uint16_t*)((char*)row[4] - sizeof(uint16_t)));
        if (charLen > 0)
        {
            real->entity = malloc(charLen + 1);
            memcpy(real->entity, (char*)row[4], charLen);
            real->entity[charLen] = '\0';
        }

        charLen = *((uint16_t*)((char*)row[5] - sizeof(uint16_t)));
        if (charLen > 0)
        {
            real->tagname = malloc(charLen + 1);
            memcpy(real->tagname, (char*)row[5], charLen);
            real->tagname[charLen] = '\0';
        }

        charLen = *((uint16_t*)((char*)row[6] - sizeof(uint16_t)));

        if (charLen > 0)
        {
            real->additional = malloc(charLen + 1);
            memcpy(real->additional, (char*)row[6], charLen);
            real->additional[charLen] = '\0';
        }

        key_len = snprintf(key, sizeof(key), "%d.%d", alarm_code, reason_code);

        if (hash_intptr_findptr(alarm_control.alarm_code_hash, key, key_len, (void**)&real->alarm) < 0 || real->alarm == NULL)
        {
            ems_syslog(LOG_ERR, "find alarm info from hash failed code: %d.%d", alarm_code, reason_code);
            destory_alarm_real(real);
            real = NULL;
            continue;
        }
        tag_t* tag = find_tag_by_name(get_proto_forward_var(), real->tagname);
        if (tag == NULL)
        {
            ems_syslog(LOG_ERR, "find alarm tag failed tag: %s", real->tagname);
            real->status = ALARM_STATUS_NO;
            real->recovery = get_time_stamp_ms();
            recovery_alarm_to_db(real);
            destory_alarm_real(real);
            real = NULL;
            continue;
        }
        // else
        // {
        //     alarm_event_t event = {0};
        //     memcpy(&event.cache, &tag->read_cache, sizeof(event.cache));
        //     if (!is_alarm(real->alarm, &event))
        //     {
        //         real->status   = ALARM_STATUS_NO;
        //         real->recovery = get_time_stamp_ms();
        //         recovery_alarm_to_db(real);
        //         destory_alarm_real(real);
        //         real = NULL;
        //         continue;
        //     }
        // }

        if (push_alarm_real_to_queue(real) != 0)
        {
            ems_syslog(LOG_ERR, "real alarm is null or push to queue failed, code: %d.%d", alarm_code, reason_code);
            if (real) destory_alarm_real(real);
        }
    }

ERR0:
    if (res != NULL)
        taos_free_result(res);
}

/* 数据库操作 */
int flush_alarm_db_to_database(alarm_db_t* alarm)
{
    if (alarm == NULL || alarm_control.db == NULL)
    {
        return -1;
    }

    char sql[512] = {0};
    snprintf(sql,
             sizeof(sql),
             INSERT_ALARM_SQL,
             alarm->raise_time,
             alarm->recovery_time,
             alarm->alarm_code,
             alarm->reason_code,
             alarm->entity,
             alarm->dev_tag_name,
             alarm->addition,
             alarm->status);
    TAOS_RES* res = taos_query(alarm_control.db, sql);
    if (res == NULL || taos_errno(res) != 0)
    {
        goto ERR0;
    }
    taos_free_result(res);
    return 0;
ERR0:
    if (res != NULL)
    {
        ems_syslog(LOG_ERR, "insret alarm: %d.%d to taosd failed: %s", alarm->alarm_code, alarm->reason_code, taos_errstr(res));
        taos_free_result(res);
    }
    return -1;
}

int recovery_alarm_to_db(alarm_real_t* alarm)
{
    alarm_db_t db_alarm    = {};
    db_alarm.alarm_code    = alarm->alarm->alarm_code;
    db_alarm.reason_code   = alarm->alarm->reason_code;
    db_alarm.entity        = alarm->entity;
    db_alarm.dev_tag_name  = alarm->tagname;
    db_alarm.addition      = alarm->additional;
    db_alarm.raise_time    = alarm->raise;
    db_alarm.recovery_time = alarm->recovery;
    db_alarm.status        = alarm->status;
    return flush_alarm_db_to_database(&db_alarm);
}

int get_alarm_history_count()
{
    if (alarm_control.db == NULL)
    {
        return 0;
    }
    int       count = 0;
    TAOS_RES* res   = taos_query(alarm_control.db, ALARM_HISTORY_NUM_GET);
    if (res == NULL || taos_errno(res) != 0)
    {
        ems_syslog(LOG_ERR, "Failed to query alarm history count: %s", taos_errstr(res));
        goto getAlarm_END;
    }
    TAOS_ROW row = taos_fetch_row(res);
    if (row != NULL)
    {
        count = *(int32_t*)row[0];
    }
getAlarm_END:
    if (res != NULL)
    {
        taos_free_result(res);
    }
    return count;
}

struct alarm_history_buf* get_alarm_history_data(int jump, int num)
{
    struct alarm_history_buf* result_info = (struct alarm_history_buf*)calloc(1, sizeof(struct alarm_history_buf));
    if (result_info == NULL)
    {
        ems_syslog(LOG_ERR, "Failure to allocate memory!");
        return NULL;
    }
    else if(alarm_control.db == NULL)
    {
        ems_syslog(LOG_ERR, "Database does not exist!");
        return NULL;
    }
    int count = get_alarm_history_count();
    if (count < 0)
    {
        ems_syslog(LOG_ERR, "Failure to get the total number of entries returns %d", count);
        count = 0;
    }
    result_info->num = count; // 计算总数
    // 准备 SQL 语句
    lbuff_init(&result_info->buff, 1024);
    lbuff_sprintf(&result_info->buff, "{\"total\":%d,\"result\":[", result_info->num);

    char sql[512] = {0};
    sprintf(sql, ALARM_HISTORY_GET_TO_UA, num, jump * num);
    TAOS_RES* res = taos_query(alarm_control.db, sql);
    if (res == NULL || taos_errno(res) != 0)
    {
        if (res != NULL) ems_syslog(LOG_ERR, "Failed to query alarm history: %s", taos_errstr(res));
        goto getAlarm_END;
    }
    TAOS_ROW row = NULL;
    uint64_t raiseTime, recoveryTime;
    int alarmCode, reasonCode;
    char* entity, *additional, *tag;
    alarm_info_t* alarm_info;
    int alarmID = jump * num;
    int           index;
    
    char dev_tag_name[DEV_NO_LEN + TAG_NAME_LEN] = {0};
    while ((row = taos_fetch_row(res)) != NULL)
    {
        tag = (char*)row[5];
        int charLen = *((uint16_t*)((char*)row[5] - sizeof(uint16_t)));
        strncpy(dev_tag_name, tag, charLen);
        dev_tag_name[charLen] = '\0';
        if (find_tag_by_name(get_proto_forward_var(), dev_tag_name) == NULL)
        {
            continue;
        }

        index        = 0;
        raiseTime    = *(int64_t*)row[0] / 1000;
        recoveryTime = *(int64_t*)row[1] / 1000;
        alarmCode    = *(int32_t*)row[2];
        reasonCode   = *(int32_t*)row[3];
        entity       = (char*)row[4];
        

        alarm_info = get_alarm_info_by_code(alarmCode, reasonCode);
        if (alarm_info == NULL)
        {
            continue;
        }

        index += sprintf(sql + index, "{\"AlarmID\": %d, \"AlarmCode\": %d, \"ReasonCode\": %d, \"Severity\": %d, \"EntityInstance\": \"", alarmID++, alarmCode, reasonCode, alarm_info->severity);

        charLen = *((uint16_t*)((char*)row[4] - sizeof(uint16_t)));
        memcpy(sql + index, entity, charLen);
        index += charLen;

        index += sprintf(sql + index, "\", \"AdditionalParam\":\"");

        if (strncmp(NO_VALUE, (char*)row[6], 6) != 0)
        {
            additional = (char*)row[6];
            int addLen = *((uint16_t*)((char*)row[6] - sizeof(uint16_t)));
            memcpy(sql + index, additional, addLen);
            index += addLen;
        }
        index += sprintf(sql + index, "\", \"RaiseTime\": %" PRIu64 ",\"RecoveryTime\": %" PRIu64 "},", raiseTime, recoveryTime);
        lbuff_append(&result_info->buff, sql, strlen(sql));
    }

    size_t len = strlen(result_info->buff.bufptr);
    if (len > 0 && result_info->buff.bufptr[len - 1] == ',')
    {
        result_info->buff.bufptr[len - 1] = '\0';
        result_info->buff.curlen -= 1;
    }

getAlarm_END:
    lbuff_sprintf(&result_info->buff, "]}");
    if (res != NULL) taos_free_result(res);
    return result_info;
}

void delete_staledated_alarm(int count)
{
    if(alarm_control.db == NULL)
    {
        ems_syslog(LOG_ERR, "Database does not exist!");
        return;
    }
    char sql[512] = {0};
    sprintf(sql, TAOS_GET_DEL_HISTORY_TIME, count);
    TAOS_RES* res = taos_query(alarm_control.db, sql);
    if (res == NULL || taos_errno(res) != 0)
    {
        if (res != NULL) ems_syslog(LOG_ERR, "Failed to query alarm history: %s", taos_errstr(res));
        goto END;
    }
    TAOS_ROW row = taos_fetch_row(res);
    if (row == NULL)
    {
        goto END;
    }
    int64_t del_time = *(int64_t*)row[0];
    taos_free_result(res);
    sprintf(sql, TAOS_DEL_HISTORY_SQL, del_time);
    res = taos_query(alarm_control.db, sql);
    if (res == NULL || taos_errno(res) != 0)
    {
        if (res != NULL) ems_syslog(LOG_ERR, "Failed to query alarm history: %s", taos_errstr(res));
        goto END;
    }

END:
    if (res != NULL) taos_free_result(res);
    return;
}


#else
#include <sqlite3.h>
int check_and_create_table(void* db);
int init_alarm_db(void** db)
{
    int ret = sqlite3_open(SQLITE3_DB_PATH, (sqlite3**)db);
    if (ret != SQLITE_OK)
    {
        ems_syslog(LOG_ERR, "sqlite3 open failed, ret=%d", ret);
        return -1;
    }

    // char sql[1024] = {0};
    // char* errmsg    = NULL;
    // snprintf(sql, sizeof(sql), CREATE_ALARM_HISTORY_DB, ALARM_DB_NAME);
    // ret = sqlite3_exec(*db, sql, NULL, NULL, &errmsg);
    // if (ret != SQLITE_OK)
    // {
    //     ems_syslog(LOG_ERR, "create alarm history db failed, ret=%s", errmsg);
    //     return -1;
    // }

    // ret = sqlite3_exec(*db, SQLITE_CREATE_ALARM_TAB_SQL, NULL, NULL, NULL);
    // if (ret != SQLITE_OK)
    // {
    //     ems_syslog(LOG_ERR, "create alarm table failed, ret=%d", ret);
    //     return -1;
    // }
    return check_and_create_table(*db);
}

int close_alarm_db(void** db)
{
    sqlite3_close(*((sqlite3**)db));
    *db = NULL;
    return 0;
}

int check_alarm_table_num_columns(void* db)
{
    int           rc;
    sqlite3_stmt* stmt;
    char sql_columns[512] = {0};
    snprintf(sql_columns, sizeof(sql_columns), "PRAGMA table_info(%s);",ALARM_REAL_TAB) ;
    rc = sqlite3_prepare_v2(db, sql_columns, -1, &stmt, 0);
    if (rc != SQLITE_OK)
    {
        ems_syslog(LOG_ERR, "Failed to prepare statement: %s\n", sqlite3_errmsg(db));
        return -1;
    }

    int num_columns = 0;
    while (sqlite3_step(stmt) == SQLITE_ROW)
    {
        num_columns++;
    }
    sqlite3_finalize(stmt);
    return num_columns;
}

int create_alarm_table(void* db)
{
    int ret = sqlite3_exec(db, SQLITE_CREATE_ALARM_TAB_SQL, NULL, NULL, NULL);
    if (ret != SQLITE_OK)
    {
        ems_syslog(LOG_ERR, "create alarm table failed, ret=%d", ret);
        return -1;
    }
    return 0;
}

int check_and_create_table(void* db)
{
    // 查询表的信息
    char* errMsg = 0;
    int           rc           = 0;
    char sql[512] = {0};
    int table_exists = 0;
    sqlite3_stmt* stmt         = NULL;
    // 查询表是否存在
    snprintf(sql, sizeof(sql), "SELECT name FROM sqlite_master WHERE type='table' AND name='%s';", ALARM_REAL_TAB);
    rc = sqlite3_prepare_v2(db, sql, -1, &stmt, 0);
    if (rc != SQLITE_OK)
    {
        ems_syslog(LOG_ERR, "Failed to prepare statement: %s\n", sqlite3_errmsg(db));
        return -1;
    }
    if (sqlite3_step(stmt) == SQLITE_ROW)
    {
        table_exists = 1;
    }
    sqlite3_finalize(stmt);

    if (!table_exists)
    {
        // 表不存在，创建表
        return create_alarm_table(db);
    }
    else
    {
        int num_columns = check_alarm_table_num_columns(db);
        if (num_columns != ALARM_REAL_TAB_NUM_COLUMN)
        {
            snprintf(sql, sizeof(sql), "DROP TABLE %s;", ALARM_REAL_TAB);
            rc = sqlite3_exec(db, sql, 0, 0, &errMsg);
            if (rc != SQLITE_OK)
            {
                ems_syslog(LOG_ERR, "SQL error: %s\n", errMsg);
                sqlite3_free(errMsg);
                return -1;
            }
            else
            {
                return create_alarm_table(db);
            }
        }
    }
    return 0;
}
extern bool is_alarm(alarm_info_t* alarm_info, tag_t* alarm);
void get_all_real_alarm_from_db()
{
    if (alarm_control.db == NULL)
    {
        return;
    }
    sqlite3_stmt* stmt;
    int           ret = sqlite3_prepare_v2(alarm_control.db, GET_ALARM_REAL_FROM_DB, -1, &stmt, NULL);
    if (ret != SQLITE_OK)
    {
        ems_syslog(LOG_ERR, "prepare sql failed: %s", sqlite3_errmsg(alarm_control.db));
        return;
    }

    int  alarm_code  = 0;
    int  reason_code = 0;
    char key[32]     = {0};
    int  key_len     = 0;

    while ((ret = sqlite3_step(stmt)) == SQLITE_ROW)
    {
        alarm_real_t* real = (alarm_real_t*)calloc(1, sizeof(alarm_real_t));
        if (real == NULL)
        {
            goto ERR0;
        }

        real->raise    = sqlite3_column_int64(stmt, 0);
        real->recovery = sqlite3_column_int64(stmt, 1);

        alarm_code  = sqlite3_column_int(stmt, 2);
        reason_code = sqlite3_column_int(stmt, 3);

        // to test
        char* entity = (char*)sqlite3_column_text(stmt, 4);
        if (entity != NULL)
        {
            real->entity = strdup(entity);
        }

        char* tag = (char*)sqlite3_column_text(stmt, 5);

        if (tag != NULL)
        {
            real->tagname = strdup(tag);
        }

        char* addition = (char*)sqlite3_column_text(stmt, 6);
        if (addition != NULL)
        {
            real->additional = strdup(addition);
        }

        real->status = sqlite3_column_int(stmt, 7);

        key_len = snprintf(key, sizeof(key), "%d.%d", alarm_code, reason_code);
        if (hash_intptr_findptr(alarm_control.alarm_code_hash, key, key_len, (void**)&real->alarm) < 0 || real->alarm == NULL)
        {
            ems_syslog(LOG_ERR, "find alarm info from hash failed code: %d.%d", alarm_code, reason_code);
            destory_alarm_real(real);
            real = NULL;
            continue;
        }
        tag_t* t = find_tag_by_name(get_proto_forward_var(), real->tagname);
        if (t == NULL)
        {
            ems_syslog(LOG_ERR, "find alarm tag failed tag: %s", real->tagname);
            real->status   = ALARM_STATUS_NO;
            real->recovery = get_time_stamp_ms();
            recovery_alarm_to_db(real);
            destory_alarm_real(real);
            real = NULL;
            continue;
        }
        // else
        // {
        //     alarm_event_t event = {0};
        //     memcpy(&event.cache, &t->read_cache, sizeof(event.cache));
        //     if (!is_alarm(real->alarm, &event))
        //     {
        //         real->status   = ALARM_STATUS_NO;
        //         real->recovery = get_time_stamp_ms();
        //         recovery_alarm_to_db(real);
        //         destory_alarm_real(real);
        //         real = NULL;
        //         continue;
        //     }
        // }

        if (push_alarm_real_to_queue(real) != 0)
        {
            ems_syslog(LOG_ERR, "real alarm is null or push to queue failed");
            if (real) destory_alarm_real(real);
        }
    }

ERR0:
    sqlite3_finalize(stmt);
}

int flush_alarm_db_to_database(alarm_db_t* alarm)
{
    if (alarm == NULL || alarm_control.db == NULL)
    {
        return -1;
    }

    char sql[512] = {0};
    snprintf(sql,
             sizeof(sql),
             INSERT_ALARM_SQL,
             alarm->raise_time,
             alarm->recovery_time,
             alarm->alarm_code,
             alarm->reason_code,
             alarm->entity,
             alarm->dev_tag_name,
             alarm->addition,
             alarm->status);

    char* errmsg = NULL;
    int   ret    = sqlite3_exec(alarm_control.db, sql, NULL, NULL, &errmsg);
    if (ret != SQLITE_OK)
    {
        ems_syslog(LOG_ERR, "insert alarm failed: %s", errmsg);
        sqlite3_free(errmsg);
        return -1;
    }
    return 0;
}

int recovery_alarm_to_db(alarm_real_t* alarm)
{
    if (alarm_control.db == NULL)
    {
        return -1;
    }
    alarm_db_t db_alarm    = {};
    db_alarm.alarm_code    = alarm->alarm->alarm_code;
    db_alarm.reason_code   = alarm->alarm->reason_code;
    db_alarm.raise_time    = alarm->raise;
    db_alarm.recovery_time = alarm->recovery;
    db_alarm.status        = alarm->status;
    char sql[512]          = {0};
    snprintf(sql, sizeof(sql), UPDATE_ALARM_SQL, db_alarm.recovery_time, db_alarm.status, db_alarm.alarm_code, db_alarm.reason_code, 1, db_alarm.raise_time);
    char* errmsg = NULL;
    int   ret    = sqlite3_exec(alarm_control.db, sql, NULL, NULL, &errmsg);
    if (ret != SQLITE_OK)
    {
        ems_syslog(LOG_ERR, "update alarm failed: %s", errmsg);
        sqlite3_free(errmsg);
        return -1;
    }
    return 0;
}

int get_alarm_history_count()
{
    if (alarm_control.db == NULL)
    {
        return -1;
    }
    int           count = 0;
    sqlite3_stmt* stmt;

    int ret = sqlite3_prepare_v2(alarm_control.db, ALARM_HISTORY_NUM_GET, -1, &stmt, NULL);
    if (ret != SQLITE_OK)
    {
        ems_syslog(LOG_ERR, "prepare sql failed: %s", sqlite3_errmsg(alarm_control.db));
        return -1;
    }

    if (sqlite3_step(stmt) == SQLITE_ROW)
    {
        count = sqlite3_column_int(stmt, 0);
    }

    sqlite3_finalize(stmt);
    return count;
}

struct alarm_history_buf* get_alarm_history_data(int jump, int num)
{
    struct alarm_history_buf* result_info = (struct alarm_history_buf*)calloc(1, sizeof(struct alarm_history_buf));
    if (result_info == NULL)
    {
        ems_syslog(LOG_ERR, "Failure to allocate memory!");
        return NULL;
    }
    else if(alarm_control.db == NULL)
    {
        ems_syslog(LOG_ERR, "Database does not exist!");
        return NULL;
    }

    int count = get_alarm_history_count();
    if (count < 0)
    {
        ems_syslog(LOG_ERR, "Failure to get the total number of entries returns -1");
        count = 0;
    }
    result_info->num = count;

    lbuff_init(&result_info->buff, 1024);
    lbuff_sprintf(&result_info->buff, "{\"total\":%d,\"result\":[", result_info->num);

    char sql[512] = {0};
    snprintf(sql, sizeof(sql), ALARM_HISTORY_GET_TO_UA, num, jump * num);

    sqlite3_stmt* stmt;
    int           ret = sqlite3_prepare_v2(alarm_control.db, sql, -1, &stmt, NULL);
    if (ret != SQLITE_OK)
    {
        ems_syslog(LOG_ERR, "prepare sql failed: %s", sqlite3_errmsg(alarm_control.db));
        goto getAlarm_END;
    }

    int alarmID = jump * num;
    while ((ret = sqlite3_step(stmt)) == SQLITE_ROW)
    {
        uint64_t      raiseTime      = sqlite3_column_int64(stmt, 0) / 1000;
        uint64_t      recoveryTime   = sqlite3_column_int64(stmt, 1) / 1000;
        int           alarmCode      = sqlite3_column_int(stmt, 2);
        int           reasonCode     = sqlite3_column_int(stmt, 3);
        char*         entityInstance = (char*)sqlite3_column_text(stmt, 4);
        char*         dev_tag_name   = (char*)sqlite3_column_text(stmt, 5);
        char*         additional     = (char*)sqlite3_column_text(stmt, 6);
        if (find_tag_by_name(get_proto_forward_var(), dev_tag_name) == NULL)
        {
            continue;
        }
        alarm_info_t* alarm_info     = get_alarm_info_by_code(alarmCode, reasonCode);
        if (alarm_info == NULL)
        {
            continue;
        }
        lbuff_sprintf(&result_info->buff,
                      "{\"AlarmID\": %d, \"AlarmCode\": %d, \"ReasonCode\": %d, \"Severity\": %d, \"EntityInstance\": \"%s\", \"AdditionalParam\": \"%s\", \"RaiseTime\": %"PRIu64",\"RecoveryTime\": %"PRIu64"},",
                      alarmID++,
                      alarm_info->alarm_code,
                      alarm_info->reason_code,
                      alarm_info->severity,
                      entityInstance,
                      additional,
                      raiseTime,
                      recoveryTime);
    }

    size_t len = strlen(result_info->buff.bufptr);
    if (len > 0 && result_info->buff.bufptr[len - 1] == ',')
    {
        result_info->buff.bufptr[len - 1] = '\0';
        result_info->buff.curlen -= 1;
    }

getAlarm_END:
    lbuff_sprintf(&result_info->buff, "]}");
    sqlite3_finalize(stmt);
    return result_info;
}

void delete_staledated_alarm(int count)
{
    if (alarm_control.db == NULL)
    {
        return;
    }
    char sql[512] = {0};
    snprintf(sql, sizeof(sql), ALARM_HISTORY_DELETE_SQL, count);
    char* errmsg = NULL;
    int ret = sqlite3_exec(alarm_control.db, sql, NULL, NULL, &errmsg);
    if (ret != SQLITE_OK){
        ems_syslog(LOG_ERR, "delete staledated alarm failed: %s", errmsg);
        sqlite3_free(errmsg);
    }
}

#endif
