#include "data_history_report.h"
#include "iectable.h"
#include "history_rcd.h"
#include "head.h"
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>

#define HISTORY_SOE_FILE_PATH    "/app/HISTORY/SOE/soe.msg"
#define HISTORY_CO_FILE_PATH     "/app/HISTORY/CO/co.msg"

/* ============================ 定值记录数据存储 ============================= */

// 定值记录数据存储数组（倒序存储，索引0=最新）
static HistorySettingRecord s_setting_records[HISTORY_SETTING_RECORD_MAX];
static uint32_t s_setting_record_count = 0;     // 实际记录数
static bool s_setting_data_loaded = false;      // 数据加载标志
static time_t s_setting_file_mtime = 0;         // 文件修改时间

// 函数前向声明
static bool parse_setting_line(const char *line, HistorySettingRecord *record);
static bool load_setting_records_from_file(void);
static bool need_reload_setting(void);
static bool parse_soe_line(const char *line, HistorySOERecord *record);
static bool load_soe_records_from_file(void);
static bool parse_co_line(const char *line, HistoryRemoteRecord *record);
static bool load_co_records_from_file(void);

/* ============================ SOE和CO记录数据存储 ============================= */

// SOE记录缓存（倒序存储，索引0=最新）
static HistorySOERecord s_soe_records[SOE_RCD_NUM];
static uint32_t s_soe_record_count = 0;
static bool s_soe_data_loaded = false;
static time_t s_soe_file_mtime = 0;

// 遥控记录缓存（倒序存储，索引0=最新）
static HistoryRemoteRecord s_co_records[CO_RCD_NUM];
static uint32_t s_co_record_count = 0;
static bool s_co_data_loaded = false;
static time_t s_co_file_mtime = 0;

// 临时记录数组（用于文件加载时倒序处理，使用静态存储避免栈溢出）
static HistorySOERecord s_soe_temp_records[SOE_RCD_NUM];
static HistoryRemoteRecord s_co_temp_records[CO_RCD_NUM];

/* ============================ 文件变更检测函数 ============================= */

static bool need_reload_soe(void)
{
    struct stat st;
    if (stat(HISTORY_SOE_FILE_PATH, &st) == 0) {
        return st.st_mtime != s_soe_file_mtime;
    }
    return false;
}

static bool need_reload_co(void)
{
    struct stat st;
    if (stat(HISTORY_CO_FILE_PATH, &st) == 0) {
        return st.st_mtime != s_co_file_mtime;
    }
    return false;
}

static bool need_reload_setting(void)
{
    struct stat st;
    if (stat(HISTORY_SETTING_FILE_PATH, &st) == 0) {
        return st.st_mtime != s_setting_file_mtime;
    }
    return false;
}

/* ============================ 测试数据集 ============================= */

// SOE事件测试数据
static HistorySOERecord s_soe_test_records[HISTORY_REPORT_TEST_SOE_NUM] = {
    {
        .record_id = 1,
        .year = 2022, .month = 10, .day = 31,
        .hour = 18, .minute = 34, .second = 55,
        .millisecond = 262,
        .event_type = 1,
        .device_name = "PLC02",
        .event_desc = "变位[值:1,通讯点:0X007c] 1"
    },
    {
        .record_id = 2,
        .year = 2022, .month = 10, .day = 31,
        .hour = 18, .minute = 34, .second = 55,
        .millisecond = 258,
        .event_type = 2,
        .device_name = "系统",
        .event_desc = "告警总 1"
    },
    {
        .record_id = 3,
        .year = 2022, .month = 10, .day = 31,
        .hour = 18, .minute = 34, .second = 45,
        .millisecond = 123,
        .event_type = 1,
        .device_name = "PLC01",
        .event_desc = "变位[值:0,通讯点:0X0010] 0"
    },
    {
        .record_id = 4,
        .year = 2022, .month = 10, .day = 31,
        .hour = 18, .minute = 34, .second = 30,
        .millisecond = 456,
        .event_type = 3,
        .device_name = "开关",
        .event_desc = "分闸动作"
    },
    {
        .record_id = 5,
        .year = 2022, .month = 10, .day = 31,
        .hour = 18, .minute = 34, .second = 15,
        .millisecond = 789,
        .event_type = 4,
        .device_name = "保护",
        .event_desc = "过流保护启动"
    }
};

// 故障事件测试数据
static HistoryFaultRecord s_fault_test_records[HISTORY_REPORT_TEST_FAULT_NUM] = {
    {
        .record_id = 1,
        .year = 2022, .month = 10, .day = 31,
        .hour = 18, .minute = 34, .second = 45,
        .millisecond = 257,
        .fault_name = "合闸回路断线",
        .fault_addr = 362,
        .fault_type = "告警",
        .ia = 0.000f, .ib = 0.000f, .ic = 0.000f, .i0 = 0.000f,
        .uab = 0.00f, .ubc = 0.00f, .uca = 0.00f,
        .freq_a = 0.00f, .freq_b = 0.00f
    },
    {
        .record_id = 2,
        .year = 2022, .month = 10, .day = 31,
        .hour = 18, .minute = 30, .second = 12,
        .millisecond = 123,
        .fault_name = "过流保护动作",
        .fault_addr = 101,
        .fault_type = "跳闸",
        .ia = 12.500f, .ib = 12.300f, .ic = 12.400f, .i0 = 0.200f,
        .uab = 10.20f, .ubc = 10.10f, .uca = 10.30f,
        .freq_a = 50.00f, .freq_b = 50.00f
    },
    {
        .record_id = 3,
        .year = 2022, .month = 10, .day = 31,
        .hour = 18, .minute = 25, .second = 30,
        .millisecond = 456,
        .fault_name = "零序保护动作",
        .fault_addr = 102,
        .fault_type = "跳闸",
        .ia = 0.150f, .ib = 0.140f, .ic = 0.160f, .i0 = 5.200f,
        .uab = 35.50f, .ubc = 35.40f, .uca = 35.60f,
        .freq_a = 50.02f, .freq_b = 49.98f
    }
};

// 遥控记录测试数据
static HistoryRemoteRecord s_remote_test_records[HISTORY_REPORT_TEST_REMOTE_NUM] = {
    {
        .record_id = 1,
        .year = 2025, .month = 10, .day = 17,
        .hour = 14, .minute = 39, .second = 10,
        .millisecond = 361,
        .control_type = "合闸",
        .exec_result = "执行终止"
    },
    {
        .record_id = 2,
        .year = 2025, .month = 10, .day = 17,
        .hour = 14, .minute = 39, .second = 10,
        .millisecond = 316,
        .control_type = "合闸",
        .exec_result = "执行确认"
    },
    {
        .record_id = 3,
        .year = 2025, .month = 10, .day = 17,
        .hour = 14, .minute = 35, .second = 22,
        .millisecond = 145,
        .control_type = "分闸",
        .exec_result = "执行成功"
    },
    {
        .record_id = 4,
        .year = 2025, .month = 10, .day = 17,
        .hour = 14, .minute = 30, .second = 15,
        .millisecond = 278,
        .control_type = "合闸",
        .exec_result = "执行成功"
    }
};



// 动作次数统计（可通过更新函数从实时数据更新）
static HistoryActionCount s_action_count = {
    .reclose_count = 0,
    .trip_count = 39
};

/* ============================ 定值记录文件读取函数 ============================= */

/**
 * @brief 解析单行定值记录
 * @param line 输入行缓冲区
 * @param record 输出记录结构体
 * @return true-解析成功, false-解析失败
 */
static bool parse_setting_line(const char *line, HistorySettingRecord *record)
{
    int year, month, day, hour, minute, second, usec;

    // 提取日期时间
    if (sscanf(line, "%d-%d-%d %d:%d:%d.%d",
               &year, &month, &day, &hour, &minute, &second, &usec) != 7) {
        return false;
    }

    record->year = (uint16_t)year;
    record->month = (uint8_t)month;
    record->day = (uint8_t)day;
    record->hour = (uint8_t)hour;
    record->minute = (uint8_t)minute;
    record->second = (uint8_t)second;
    // 微秒转毫秒（取前3位）
    record->millisecond = (uint16_t)(usec / 1000);

    // 查找定值名称（时间后的空格，即第二个空格，到左括号前）
    // 数据格式: "2026-02-25 14:05:03.108908 定值名称(类别)由:旧值改:新值"
    // 第一个空格在日期后，第二个空格在时间后
    const char *first_space = strchr(line, ' ');  // 找到日期后的空格
    if (!first_space) return false;

    const char *second_space = strchr(first_space + 1, ' ');  // 找到时间后的空格
    if (!second_space) return false;

    const char *name_start = second_space + 1;  // 定值名称开始位置

    const char *paren_start = strchr(name_start, '(');
    if (!paren_start) return false;

    // 提取定值名称
    size_t name_len = paren_start - name_start;
    if (name_len == 0) {
        return false;
    }
    if (name_len >= sizeof(record->setting_name)) {
        name_len = sizeof(record->setting_name) - 1;
    }
    strncpy(record->setting_name, name_start, name_len);
    record->setting_name[name_len] = '\0';

    // 提取括号内的类别信息
    const char *category_start = paren_start + 1;
    const char *paren_end = strchr(category_start, ')');
    if (!paren_end) return false;
    
    size_t category_len = paren_end - category_start;
    if (category_len >= sizeof(record->setting_category)) {
        category_len = sizeof(record->setting_category) - 1;
    }
    strncpy(record->setting_category, category_start, category_len);
    record->setting_category[category_len] = '\0';

    // 查找"由:"标记
    const char *you_marker = strstr(paren_end, "由:");
    if (!you_marker) return false;

    // 查找"改:"标记
    const char *gai_marker = strstr(you_marker, "改:");
    if (!gai_marker) return false;

    // 提取旧值字符串（"由:"之后，"改:"之前）
    const char *old_val_start = you_marker + 2; // 跳过"由:"
    size_t old_val_len = gai_marker - old_val_start;
    if (old_val_len >= sizeof(record->old_value)) {
        old_val_len = sizeof(record->old_value) - 1;
    }
    if (old_val_len == 0) {
        record->old_value[0] = '\0';
    } else {
        strncpy(record->old_value, old_val_start, old_val_len);
        record->old_value[old_val_len] = '\0';
        // 清理特殊字符
        char *p = record->old_value;
        while (*p) {
            if (*p == '\r' || *p == '\n' || (unsigned char)*p == 0x00) {
                *p = '\0';
                break;
            }
            p++;
        }
    }

    // 提取新值字符串（"改:"之后，行尾）
    const char *new_val_start = gai_marker + 2; // 跳过"改:"
    const char *val_end = new_val_start;
    while (*val_end && *val_end != '\r' && *val_end != '\n' && (unsigned char)*val_end != 0x00) {
        val_end++;
    }
    size_t new_val_len = val_end - new_val_start;
    if (new_val_len >= sizeof(record->new_value)) {
        new_val_len = sizeof(record->new_value) - 1;
    }
    if (new_val_len == 0) {
        record->new_value[0] = '\0';
    } else {
        strncpy(record->new_value, new_val_start, new_val_len);
        record->new_value[new_val_len] = '\0';
        // 清理特殊字符
        char *p = record->new_value;
        while (*p) {
            if (*p == '\r' || *p == '\n' || (unsigned char)*p == 0x00) {
                *p = '\0';
                break;
            }
            p++;
        }
    }

    record->unit[0] = '\0';

    return true;
}

/**
 * @brief 从文件加载定值记录数据（逆序存储，最新记录在前）
 * @return true-成功, false-失败
 * @note 先正序读取到数组，然后原地反转，无需额外临时数组
 */
static bool load_setting_records_from_file(void)
{
    FILE *fp = fopen(HISTORY_SETTING_FILE_PATH, "r");
    if (!fp) {
        s_setting_record_count = 0;
        s_setting_data_loaded = true;
        return false;
    }

    struct stat st;
    if (stat(HISTORY_SETTING_FILE_PATH, &st) == 0) {
        s_setting_file_mtime = st.st_mtime;
    }

    char line[HISTORY_SETTING_LINE_MAX_LEN];
    uint32_t count = 0;

    while (fgets(line, sizeof(line), fp) != NULL) {
        if (line[0] == '\0' || line[0] == '\r' || line[0] == '\n') {
            continue;
        }
        if (count >= HISTORY_SETTING_RECORD_MAX) {
            break;
        }

        HistorySettingRecord record = {0};
        if (parse_setting_line(line, &record)) {
            s_setting_records[count++] = record;
        }
    }

    fclose(fp);

    // 原地反转数组，使最新记录在前
    for (uint32_t i = 0; i < count / 2; i++) {
        HistorySettingRecord temp = s_setting_records[i];
        s_setting_records[i] = s_setting_records[count - 1 - i];
        s_setting_records[count - 1 - i] = temp;
    }

    // 重新分配记录ID（1表示最新）
    for (uint32_t i = 0; i < count; i++) {
        s_setting_records[i].record_id = i + 1;
    }

    s_setting_record_count = count;
    s_setting_data_loaded = true;
    return true;
}

/* ============================ 点号名称获取封装函数 ============================= */

/**
 * @brief 通过通讯点号查找遥控点表索引
 * @param point_id 通讯点号
 * @return 点表索引，未找到返回-1
 */
static int find_do_table_index(uint16_t point_id)
{
    extern struct table_file_head_data *g_table_head;
    extern struct do_table *g_do_table;

    if (g_table_head == NULL || g_do_table == NULL) {
        return -1;
    }

    for (uint32_t i = 0; i < g_table_head->do_num; i++) {
        if (g_do_table[i].cp == point_id) {
            return (int)i;
        }
    }
    return -1;
}

static void get_point_name(uint16_t point_id, uint8_t res_type, char *name, size_t name_len)
{
    if (name == NULL || name_len == 0) {
        return;
    }

    int tbl_index = -1;

    // 遥控记录(YK)需要特殊处理，通过遍历g_do_table查找
    if (res_type == RES_TYPE_YK) {
        tbl_index = find_do_table_index(point_id);
    } else {
        // SOE等DI点号使用原有的tbl_cp2index查询
        tbl_index = tbl_cp2index(point_id);
    }

    if (tbl_index >= 0) {
        tbl_getname(res_type, tbl_index, name);
    } else {
        strncpy(name, "未知点号", name_len - 1);
        name[name_len - 1] = '\0';
    }
}

/* ============================ SOE记录解析函数 ============================= */

static bool parse_soe_line(const char *line, HistorySOERecord *record)
{
    unsigned int point_id, value;
    int year, month, day, hour, minute, second, msec;

    if (line[0] == '\0' || line[0] == '\r' || line[0] == '\n') {
        return false;
    }
    if (strstr(line, "文件头") != NULL || strstr(line, "D30") != NULL) {
        return false;
    }

    const char *data_start = strstr(line, "0x");
    if (!data_start) return false;

    if (sscanf(data_start, "0x%x,%d,%d-%d-%d %d:%d:%d.%d",
               &point_id, &value,
               &year, &month, &day,
               &hour, &minute, &second, &msec) != 9) {
        return false;
    }

    record->point_id = (uint16_t)point_id;
    record->value = (uint8_t)value;
    record->year = (uint16_t)year;
    record->month = (uint8_t)month;
    record->day = (uint8_t)day;
    record->hour = (uint8_t)hour;
    record->minute = (uint8_t)minute;
    record->second = (uint8_t)second;
    record->millisecond = (uint16_t)msec;
    record->point_owner = 0;
    record->point_index = 0;
    record->event_type = 0;
    record->device_name[0] = '\0';
    record->event_desc[0] = '\0';

    return true;
}

/* ============================ CO记录解析函数 ============================= */

static bool parse_co_line(const char *line, HistoryRemoteRecord *record)
{
    unsigned int point_id;
    int year, month, day, hour, minute, second, msec;
    char control_type[16], exec_result[16];

    if (line[0] == '\0' || line[0] == '\r' || line[0] == '\n') {
        return false;
    }
    if (strstr(line, "文件头") != NULL || strstr(line, "D30") != NULL) {
        return false;
    }

    const char *data_start = strstr(line, "0x");
    if (!data_start) return false;

    if (sscanf(data_start, "0x%x,%15[^,],%15[^,],%d-%d-%d %d:%d:%d.%d",
               &point_id, control_type, exec_result,
               &year, &month, &day,
               &hour, &minute, &second, &msec) != 10) {
        return false;
    }

    record->point_id = (uint16_t)point_id;
    strncpy(record->control_type, control_type, sizeof(record->control_type) - 1);
    record->control_type[sizeof(record->control_type) - 1] = '\0';
    strncpy(record->exec_result, exec_result, sizeof(record->exec_result) - 1);
    record->exec_result[sizeof(record->exec_result) - 1] = '\0';
    record->year = (uint16_t)year;
    record->month = (uint8_t)month;
    record->day = (uint8_t)day;
    record->hour = (uint8_t)hour;
    record->minute = (uint8_t)minute;
    record->second = (uint8_t)second;
    record->millisecond = (uint16_t)msec;
    record->point_owner = 0;
    record->point_index = 0;

    return true;
}

/* ============================ SOE记录加载函数 ============================= */

static bool load_soe_records_from_file(void)
{
    FILE *fp = fopen(HISTORY_SOE_FILE_PATH, "r");
    if (!fp) {
        s_soe_record_count = 0;
        s_soe_data_loaded = true;
        return false;
    }

    struct stat st;
    if (stat(HISTORY_SOE_FILE_PATH, &st) == 0) {
        s_soe_file_mtime = st.st_mtime;
    }

    char line[256];
    uint32_t count = 0;

    while (fgets(line, sizeof(line), fp) != NULL && count < SOE_RCD_NUM) {
        if (parse_soe_line(line, &s_soe_temp_records[count])) {
            count++;
        }
    }
    fclose(fp);
    s_soe_record_count = count;
    for (uint32_t i = 0; i < count; i++) {
        s_soe_records[i] = s_soe_temp_records[count - 1 - i];
        s_soe_records[i].record_id = i + 1;
        get_point_name(s_soe_records[i].point_id, RES_TYPE_YX,
                       s_soe_records[i].point_name,
                       sizeof(s_soe_records[i].point_name));
    }
    s_soe_data_loaded = true;
    return true;
}

/* ============================ CO记录加载函数 ============================= */

static bool load_co_records_from_file(void)
{
    FILE *fp = fopen(HISTORY_CO_FILE_PATH, "r");
    if (!fp) {
        s_co_record_count = 0;
        s_co_data_loaded = true;
        return false;
    }

    struct stat st;
    if (stat(HISTORY_CO_FILE_PATH, &st) == 0) {
        s_co_file_mtime = st.st_mtime;
    }

    char line[256];
    uint32_t count = 0;

    while (fgets(line, sizeof(line), fp) != NULL && count < CO_RCD_NUM) {
        if (parse_co_line(line, &s_co_temp_records[count])) {
            count++;
        }
    }
    fclose(fp);

    s_co_record_count = count;
    for (uint32_t i = 0; i < count; i++) {
        // printf("%s line %u: point_id=0x%04x\n", __FUNCTION__, i, s_co_temp_records[i].point_id);
        s_co_records[i] = s_co_temp_records[count - 1 - i];
        s_co_records[i].record_id = i + 1;
        get_point_name(s_co_records[i].point_id, RES_TYPE_YK,
                       s_co_records[i].point_name,
                       sizeof(s_co_records[i].point_name));
    }

    s_co_data_loaded = true;
    return true;
}



/* ============================ 接口函数实现 ============================= */

/**
 * @brief 获取指定类型的记录总数
 */
uint32_t data_history_report_get_count(HistoryReportType type)
{
    switch (type) {
        case HISTORY_REPORT_SOE:
            if (!s_soe_data_loaded || need_reload_soe()) {
                load_soe_records_from_file();
            }
            return s_soe_record_count;
        case HISTORY_REPORT_FAULT:
            return HISTORY_REPORT_TEST_FAULT_NUM;
        case HISTORY_REPORT_REMOTE:
            if (!s_co_data_loaded || need_reload_co()) {
                load_co_records_from_file();
            }
            return s_co_record_count;
        case HISTORY_REPORT_SETTING:
            if (!s_setting_data_loaded || need_reload_setting()) {
                load_setting_records_from_file();
            }
            return s_setting_record_count;
        case HISTORY_REPORT_ACTION_COUNT:
            return 1;  // 动作次数只有一条统计记录
        default:
            return 0;
    }
}

/**
 * @brief 获取SOE事件记录
 */
bool data_history_report_get_soe_record(uint32_t index, HistorySOERecord *record)
{
    if (!s_soe_data_loaded || need_reload_soe()) {
        load_soe_records_from_file();
    }

    if (record == NULL || index >= s_soe_record_count) {
        return false;
    }

    *record = s_soe_records[index];
    return true;
}

/**
 * @brief 获取故障事件记录
 */
bool data_history_report_get_fault_record(uint32_t index, HistoryFaultRecord *record)
{
    if (record == NULL || index >= HISTORY_REPORT_TEST_FAULT_NUM) {
        return false;
    }
    
    memcpy(record, &s_fault_test_records[index], sizeof(HistoryFaultRecord));
    return true;
}

/**
 * @brief 获取遥控记录
 */
bool data_history_report_get_remote_record(uint32_t index, HistoryRemoteRecord *record)
{
    if (!s_co_data_loaded || need_reload_co()) {
        load_co_records_from_file();
    }

    if (record == NULL || index >= s_co_record_count) {
        return false;
    }

    *record = s_co_records[index];
    return true;
}

/**
 * @brief 获取定值记录
 */
bool data_history_report_get_setting_record(uint32_t index, HistorySettingRecord *record)
{
    if (!s_setting_data_loaded || need_reload_setting()) {
        load_setting_records_from_file();
    }

    if (record == NULL || index >= s_setting_record_count) {
        return false;
    }

    memcpy(record, &s_setting_records[index], sizeof(HistorySettingRecord));
    return true;
}

/**
 * @brief 从实时数据更新动作次数统计
 */
void data_history_report_update_action_count(void)
{
    // printf("%s: 更新动作次数统计\n", __FUNCTION__);
    // 清零静态数组
    s_action_count.reclose_count = 0;
    s_action_count.trip_count = 0;

    // 遍历所有开关累加次数
    for (int sw = 0; sw < SWITCH_NUM_MAX; sw++) {
        s_action_count.reclose_count += scaio_get_num(sw, 1);  // 合闸
        s_action_count.trip_count += scaio_get_num(sw, 0);     // 跳闸
    }
}

/**
 * @brief 获取动作次数统计
 */
bool data_history_report_get_action_count(HistoryActionCount *count)
{
    if (count == NULL) {
        return false;
    }
    memcpy(count, &s_action_count, sizeof(HistoryActionCount));
    return true;
}

/**
 * @brief 初始化历史报告测试数据
 */
void data_history_report_init(void)
{
    // 加载定值记录数据
    if (!s_setting_data_loaded) {
        load_setting_records_from_file();
    }
    
    // 初始化动作次数统计数据
    data_history_report_update_action_count();
}
