#include "bmser_alarm.h"
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <sys/syslog.h>
#include "../common.h"

static int bmser_init_db(void** db);
static int bmser_close_db(void *db);
static int bmser_alarm_search(void* db, bmser_alarm_t* alarm_l, char* entity, int offset, int limit);
static int bmser_alarm_total(void* db, char* entity);

int get_bmser_alarm_buf(struct lnxall_buff* buf, char* entity, int page, int page_size)
{
    if (buf == NULL || entity == NULL || page_size == 0)
    {
        return -1;
    }

    int offset = page * page_size;
    int limit  = page_size;
    int ret    = -1;
    int size   = 0;
    void* db = NULL;
    bmser_alarm_t* alarm = NULL;
    if (bmser_init_db(&db) != 0)
    {
        goto END;
    }


    int total = bmser_alarm_total(db, entity);
    if (total <= 0)
    {
        total = 0;
        goto END;
    }

    alarm = malloc(sizeof(bmser_alarm_t) * limit);
    size = bmser_alarm_search(db, alarm, entity, offset, limit);
    if (size <= 0)
    {
        goto END;
    }

    lbuff_sprintf(buf, "{\"total\":%d,\"alarms\":[", total);
    for (int i = 0; i < size; i++)
    {
        lbuff_append(buf, alarm[i].frame, strlen(alarm[i].frame));
        lbuff_append(buf, ",", 1);
    } 
    buf->bufptr[buf->curlen - 1] = ']';
    lbuff_append(buf, "}", 1);

    ret = 0;

END:
    if (buf->curlen == 0) lbuff_sprintf(buf, "{\"total\":%d, \"alarms\":[]}", total);
    if (alarm) free(alarm);
    if(db) bmser_close_db(db);
    return ret;
}


#ifdef EN_TDENGINE
#include "../database/taos_database.h"
static int bmser_init_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};

    TAOS_RES* res = taos_query(*db, CREATE_ALARM_HISTORY_DB);

    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;
    }
    taos_free_result(res);
    snprintf(sql, sizeof(sql), "use %s", BMSER_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;
    }
    taos_free_result(res);
    return 0;
}

static int bmser_close_db(void *db)
{
    if (db)
    {
        taos_close(db);
    }
    return 0;
}

static int bmser_alarm_total(void* db, char* entity)
{
    if (entity == NULL || db == NULL)
    {
        ems_syslog(LOG_ERR, "bmser_alarm_ctrl is null");
        return -1;
    }
    int  total    = -1;
    char sql[512] = {0};
    sprintf(sql, ALARM_HISTORY_NUM_GET, entity);
    TAOS_RES* res = taos_query(db, sql);
    if (res == NULL)
    {
        ems_syslog(LOG_ERR, "get alarm total failed");
        goto END;
    }
    if (taos_errno(res) != 0)
    {
        ems_syslog(LOG_ERR, "get alarm total failed, err=%s", taos_errstr(res));
        goto END;
    }

    TAOS_ROW row = taos_fetch_row(res);
    if (row == NULL)
    {
        ems_syslog(LOG_ERR, "get alarm total failed, row is null");
        goto END;
    }
    total = *(int*)row[0];
END:
    if (res) taos_free_result(res);
    return total;
}

static int bmser_alarm_search(void* db, bmser_alarm_t* alarm_l, char* entity, int offset, int limit)
{
    if (alarm_l == NULL || db == NULL)
    {
        ems_syslog(LOG_ERR, "bmser_alarm_ctrl is null");
        return -1;
    }
    int i = 0;

    char sql[512] = {0};
    sprintf(sql, GET_BMSER_ALARM_HISTORY, entity, limit, offset);
    TAOS_RES* res = taos_query(db, sql);
    if (res == NULL)
    {
        ems_syslog(LOG_ERR, "get alarm total failed");
        goto END;
    }

    if (taos_errno(res) != 0)
    {
        ems_syslog(LOG_ERR, "get alarm total failed, err=%s", taos_errstr(res));
        goto END;
    }

    TAOS_ROW row = NULL;
    while ((row  = taos_fetch_row(res)) != NULL)
    {
        bmser_alarm_t* alarm = &alarm_l[i++];
        alarm->raise_time = *(int64_t*)row[0];
        int charLen = *((uint16_t*)((char*)row[1] - sizeof(uint16_t)));
        if (charLen > 0)
        {
            memcpy(alarm->entity, (char*)row[1], charLen);
            alarm->entity[charLen] = '\0';
        }
        charLen = *((uint16_t*)((char*)row[2] - sizeof(uint16_t)));
        if (charLen > 0)
        {
            alarm->frame = malloc(charLen + 1);
            memcpy(alarm->frame, (char*)row[2], charLen);
            alarm->frame[charLen] = '\0';
        }
    }

END:
    if (res) taos_free_result(res);
    return i;
}

#else
#include "sqlite3.h"

static int bmser_init_db(void** db)
{
    int ret = sqlite3_open(BMSER_ALARM_DB_PATH, (sqlite3**)(db));
    if (ret != SQLITE_OK)
    {
        ems_syslog(LOG_ERR, "sqlite3 open failed, ret=%d", ret);
        return -1;
    }
    return 0;
}

static int bmser_close_db(void* db)
{
    if (db)
    {
        sqlite3_close(db);
    }
    return 0;
}

static int bmser_alarm_total(void*db,char* entity)
{
    if (entity == NULL || db == NULL)
    {
        ems_syslog(LOG_ERR, "bmser_alarm_ctrl is null");
        return -1;
    }
    int  total    = -1;
    char sql[512] = {0};
    sqlite3_stmt* stmt     = NULL;
    sprintf(sql, ALARM_HISTORY_NUM_GET, entity);
    int ret = sqlite3_prepare_v2(db , sql, -1, &stmt, NULL);
    if (ret != SQLITE_OK)
    {
        ems_syslog(LOG_ERR, "prepare sql failed: %s", sqlite3_errmsg(db));
        goto END;
    }

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

END:
    if (stmt) sqlite3_finalize(stmt);
    return total;
}

static int bmser_alarm_search(void*db, bmser_alarm_t* alarm, char* entity, int offset, int limit)
{
    if (db == NULL || alarm == NULL)
    {
        ems_syslog(LOG_ERR, "bmser_alarm_ctrl is null");
        return -1;
    }
    int i = 0;
    int  ret      = -1;
    char sql[512] = {0};
    sprintf(sql, GET_BMSER_ALARM_HISTORY, entity, limit, offset);
    sqlite3_stmt* stmt = NULL;
    ret = sqlite3_prepare_v2(db, sql, -1, &stmt, NULL);
    if (ret != SQLITE_OK)
    {
        ems_syslog(LOG_ERR, "prepare sql failed: %s", sqlite3_errmsg(db));
        goto END;
    }

    while ((ret = sqlite3_step(stmt)) == SQLITE_ROW)
    {
        bmser_alarm_t* tmp        = &alarm[i++];
        uint64_t       raise_time = sqlite3_column_int64(stmt, 0);
        char*          entity     = (char*)sqlite3_column_text(stmt, 1);
        char*          frame      = (char*)sqlite3_column_text(stmt, 2);
        tmp->raise_time = raise_time;
        if (entity)
            strncpy(tmp->entity, entity, sizeof(tmp->entity));
        if(frame)
            tmp->frame = strdup(frame);
    }

END:
    if (stmt) sqlite3_finalize(stmt);
    return i;
}

#endif
