
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <time.h>
#include <regex.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <net/if.h> 
#include <sys/ioctl.h>
#include <netinet/in.h>
#include <net/if.h>
#include <arpa/inet.h>
#include "common_utils.h"
#include <pthread.h>

/**
 * 读取文件内容到内存缓冲区
 * @param file 文件路径
 * @param len [out] 可选参数，用于返回文件长度
 * @return 成功返回数据指针(需调用者释放)，失败返回NULL
 */
char *read_file_data_and_lens(const char *file, int *len) 
{
    char *data = NULL;
    FILE *fp = NULL;

    // 打开文件（二进制模式避免文本转换问题）
    fp = fopen(file, "rb");
    if (fp == NULL) 
    {
        fprintf(stderr, "[UTILS] 打开文件失败: %s\n", file);
        return NULL;
    }

    // 获取文件大小
    if (fseek(fp, 0, SEEK_END) != 0) {
        fprintf(stderr, "[UTILS] 文件定位失败 (errno:%d)\n", errno);
        fclose(fp);
        return NULL;
    }
    long size = ftell(fp);
    if (size == -1L) {
        fprintf(stderr, "[UTILS] 获取文件大小失败 (errno:%d)\n", errno);
        fclose(fp);
        return NULL;
    }
    rewind(fp);  // 重置文件指针

    // 分配内存（+1用于字符串终止符）
    data = (char *)malloc(size + 1);
    if (!data) 
    {
        fclose(fp);
        fprintf(stderr, "[UTILS] 内存分配失败: %ld bytes\n", size + 1);
        return NULL;
    }

    // 读取文件内容
    size_t read_size = fread(data, 1, size, fp);
    fclose(fp);

    if (read_size != (size_t)size) 
    {
        free(data);
        fprintf(stderr, "[UTILS] 读取不完全: %zu/%ld bytes\n", read_size, size);
        return NULL;
    }

    data[size] = '\0';  // 添加字符串终止符

    if (len != NULL) 
    {
        *len = size;
    }

    return data;
}


/**
 * 安全读取文件内容到内存缓冲区
 * @param file 文件路径(非空)
 * @return 成功返回数据指针(需调用者free)，失败返回NULL
 * 
 * 改进点：
 * 1. 增加参数校验
 * 2. 使用二进制模式避免文本转换问题
 * 3. 检查文件读取完整性
 * 4. 统一错误处理流程
 * 5. 规范代码格式
 */
char* read_file_datas(const char* file) 
{
    // 参数校验
    if (file == NULL) 
    {
        fprintf(stderr, "[UTILS] 错误：空文件路径\n");
        return NULL;
    }

    // 二进制模式打开文件
    FILE* fp = fopen(file, "rb");
    if (fp == NULL) 
    {
        fprintf(stderr, "[UTILS] 无法打开文件: %s (errno:%d)\n", file, errno);
        return NULL;
    }

    // 获取文件大小
    if (fseek(fp, 0, SEEK_END) != 0) {
        fprintf(stderr, "[UTILS] 文件定位失败 (errno:%d)\n", errno);
        fclose(fp);
        return NULL;
    }
    long size = ftell(fp);
    if (size == -1L) {
        fprintf(stderr, "[UTILS] 获取文件大小失败 (errno:%d)\n", errno);
        fclose(fp);
        return NULL;
    }
    rewind(fp);  // 重置文件指针

    // 分配内存(+1用于字符串终止符)
    char* data = (char*)malloc(size + 1);
    if (data == NULL) 
    {
        fclose(fp);
        fprintf(stderr, "[UTILS] 内存分配失败: %ld bytes\n", size + 1);
        return NULL;
    }

    // 读取文件内容
    size_t read_size = fread(data, 1, size, fp);
    fclose(fp); // 无论成功与否都立即关闭文件

    if (read_size != (size_t)size) 
    {
        free(data);
        fprintf(stderr, "[UTILS] 读取不完全: %zu/%ld bytes\n", read_size, size);
        return NULL;
    }

    data[size] = '\0'; // 添加字符串终止符

    return data;
}



/**
 * 安全写入数据到文件
 * @param file 目标文件路径(非空)
 * @param data 要写入的数据(非空)
 * @param len 数据长度(>0)
 * @return 成功返回0，失败返回-1
 */
int write_file_data(const char *file,  char *data, int len) 
{
    // 参数校验
    if (file == NULL || *file == '\0') 
    {
        fprintf(stderr, "[UTILS] 错误：空文件路径\n");
        return -1;
    }
    
    if (data == NULL || len <= 0) 
    {
        fprintf(stderr, "[UTILS] 错误：无效数据参数\n");
        return -1;
    }

    // 以二进制模式写入（避免文本转换问题）
    FILE *fp = fopen(file, "wb");
    if (fp == NULL) 
    {
        fprintf(stderr, "[UTILS] 无法打开文件: %s (errno:%d)\n", file, errno);
        return -1;
    }

    // 实际写入检查
    size_t written = fwrite(data, sizeof(char), len, fp);
    if (written != (size_t)len) 
    {
        fprintf(stderr, "[UTILS] 写入不完全: %zu/%d bytes\n", written, len);
        fclose(fp);
        return -1;
    }

    // 确保数据刷入磁盘
    if (fflush(fp) != 0) 
    {
        fprintf(stderr, "[UTILS] 数据刷新失败 (errno:%d)\n", errno);
        fclose(fp);
        return -1;
    }

    fclose(fp);
    return 0;
}

// 安全字符串拷贝函数（适配emsd/src组件规范）
void safe_strncpy(char *dest, const char *src, size_t dest_size)
{
    if (dest == NULL || src == NULL || dest_size == 0) {
        fprintf(stderr, "[UTILS] 错误：无效参数\n");
        return;
    }

    size_t i;
    for (i = 0; i < dest_size - 1 && src[i] != '\0'; i++) {
        dest[i] = src[i];
    }
    dest[i] = '\0'; // 确保终止符
}

/**
 * @brief 从文件中读取软件版本号
 * @param software_version 用于存储版本号的字符数组
 * @param file_path 版本号文件路径
 * @return 0成功，-1失败
 */
int get_software_version(char *software_version, const char *file_path) {
    if (!software_version || !file_path) {
        fprintf(stderr, "Error: Invalid input parameters.\n");
        return -1;
    }

    FILE *file = fopen(file_path, "r");
    if (!file) {
        fprintf(stderr, "Error: Failed to open file '%s' (%s).\n", file_path, strerror(errno));
        return -1;
    }

    // 读取文件内容（假设版本号在第一行）
    char buffer[256];
    if (!fgets(buffer, sizeof(buffer), file)) {
        fprintf(stderr, "Error: Failed to read from file '%s' (%s).\n", file_path, strerror(errno));
        fclose(file);
        return -1;
    }

    fclose(file);

    // 去除换行符（如果有）
    buffer[strcspn(buffer, "\n")] = '\0';

    // 检查版本号长度是否合法
    if (strlen(buffer) == 0) {
        fprintf(stderr, "Error: Empty version string in file '%s'.\n", file_path);
        return -1;
    }

    // 复制版本号到输出数组
    strncpy(software_version, buffer, strlen(buffer));
    software_version[strlen(buffer)] = '\0'; // 确保字符串终止

    return 0;
}


/**
 * @brief 将软件版本号写入文件
 * @param software_version 待写入的版本号字符串
 * @param file_path 版本号文件路径
 * @return 0成功，-1失败
 */
int set_software_version(const char *software_version, const char *file_path) {
    if (!software_version || !file_path) {
        fprintf(stderr, "Error: Invalid input parameters.\n");
        return -1;
    }

    // 检查版本号是否为空
    if (strlen(software_version) == 0) {
        fprintf(stderr, "Error: Version string is empty.\n");
        return -1;
    }

    FILE *file = fopen(file_path, "w");
    if (!file) {
        fprintf(stderr, "Error: Failed to open file '%s' for writing (%s).\n", file_path, strerror(errno));
        return -1;
    }

    // 写入版本号到文件
    if (fprintf(file, "%s\n", software_version) < 0) {
        fprintf(stderr, "Error: Failed to write to file '%s' (%s).\n", file_path, strerror(errno));
        fclose(file);
        return -1;
    }

    fclose(file);
    return 0;
}


int check_timeout_second(time_t now, time_t *prev, int timeout_s)
{
    if (now - (*prev) < timeout_s)
    {
        return 0;
    }

    *prev = now;

    return 1;
}

int check_timeout_msecond(long long now, long long *prev, int timeout_ms)
{
    if (now - (*prev) < timeout_ms)
    {
        return 0;
    }

    *prev = now;

    return 1;
}

int get_localip(const char *eth_name, char *local_ip_addr, size_t buffer_size) {
    // 参数校验
    if (eth_name == NULL || local_ip_addr == NULL || buffer_size == 0) {
        fprintf(stderr, "Error: Invalid arguments\n");
        return -1;
    }

    int fd = -1;
    struct ifreq ifr;
    memset(&ifr, 0, sizeof(ifr)); // 清零结构体

    // 创建socket
    fd = socket(AF_INET, SOCK_DGRAM, 0);
    if (fd < 0) {
        perror("Error: Failed to create socket");
        return -1;
    }

    // 设置网络接口名称
    strncpy(ifr.ifr_name, eth_name, IFNAMSIZ - 1);
    ifr.ifr_name[IFNAMSIZ - 1] = '\0'; // 确保字符串终止

    // 获取IP地址
    if (ioctl(fd, SIOCGIFADDR, &ifr) < 0) {
        perror("Error: Failed to get IP address");
        close(fd);
        return -1;
    }

    // 提取IP地址
    struct sockaddr_in *sin = (struct sockaddr_in *)&ifr.ifr_addr;
    if (sin->sin_family != AF_INET) {
        fprintf(stderr, "Error: Not an IPv4 address\n");
        close(fd);
        return -1;
    }

    const char *ip_str = inet_ntoa(sin->sin_addr);
    if (ip_str == NULL) {
        fprintf(stderr, "Error: Invalid IP address\n");
        close(fd);
        return -1;
    }

    // 检查缓冲区大小是否足够
    size_t ip_len = strlen(ip_str);
    if (ip_len >= buffer_size) {
        fprintf(stderr, "Error: Buffer too small for IP address\n");
        close(fd);
        return -1;
    }

    // 复制IP地址到输出缓冲区
    strncpy(local_ip_addr, ip_str, buffer_size - 1);
    local_ip_addr[buffer_size - 1] = '\0'; // 确保字符串终止

    // 关闭socket
    close(fd);
    return 0;
}

/**
 * Safe string copy with length limitation (strlcpy implementation)
 * @param dest      Destination buffer (must not be NULL)
 * @param src       Source string (must not be NULL)
 * @param dest_size Size of destination buffer (including null terminator)
 * @return          Length of src string (excluding null terminator)
 * 
 * Features:
 * 1. Always null-terminates destination when dest_size > 0
 * 2. Returns length of src for truncation detection
 * 3. More robust than strncpy
 */
size_t local_strlcpy(char *dest, const char *src, size_t dest_size)
{
    /* Handle NULL pointer cases defensively */
    if (dest == NULL || src == NULL) {
        if (dest != NULL && dest_size > 0) {
            dest[0] = '\0';  /* Ensure empty string if dest is valid */
        }
        return 0;  /* Return 0 to indicate invalid parameters */
    }

    /* Special case: zero-sized destination buffer */
    if (dest_size == 0) {
        return strlen(src);
    }

    /* Calculate lengths only once for efficiency */
    const size_t src_len = strlen(src);
    const size_t copy_len = (src_len < dest_size) ? src_len : (dest_size - 1);

    /* Perform the actual copy operation */
    memcpy(dest, src, copy_len);
    dest[copy_len] = '\0';  /* Guarantee null-termination */

    return src_len;  /* Return source length per strlcpy convention */
}


/**
 * @brief 从 dev_tag_name 中提取 dev_no（兼容两种格式）
 * @param dev_tag_name 设备标签名称，格式为 "PCS.ActPower" 或 "LC1.PCS.ActPower"
 * @param dev_no 输出参数，用于存储提取的 dev_no
 * @param dev_no_size dev_no 缓冲区的大小
 * @return 成功返回 0，失败返回 -1（如输入无效或缓冲区不足）
 */
int extract_dev_no(const char *dev_tag_name, char *dev_no, size_t dev_no_size) {
    if (dev_tag_name == NULL || dev_no == NULL || dev_no_size == 0) {
        return -1; // 输入参数无效
    }

    // 统计点的数量
    int dot_count = 0;
    const char *dot_pos[2] = {NULL, NULL}; // 存储两个点的位置
    const char *p = dev_tag_name;

    while (*p != '\0') {
        if (*p == '.') {
            if (dot_count < 2) {
                dot_pos[dot_count] = p;
            }
            dot_count++;
        }
        p++;
    }

    // 根据点的数量决定提取逻辑
    const char *start_pos = NULL;
    const char *end_pos = NULL;

    if (dot_count == 1) {
        // 格式：PCS.ActPower
        start_pos = dev_tag_name;
        end_pos = dot_pos[0];
    } else if (dot_count == 2) {
        // 格式：LC1.PCS.ActPower
        start_pos = dot_pos[0] + 1; // 跳过第一个点
        end_pos = dot_pos[1];
    } else {
        return -1; // 格式不符合预期
    }

    // 计算 dev_no 的长度
    size_t dev_no_length = end_pos - start_pos;

    // 检查缓冲区是否足够
    if (dev_no_length >= dev_no_size) {
        return -1; // 缓冲区不足
    }

    // 提取 dev_no
    strncpy(dev_no, start_pos, dev_no_length);
    dev_no[dev_no_length] = '\0'; // 确保字符串终止

    return 0;
}


#define MAX_TIMESTAMP_LEN 64
int format_timestamp_safe(uint64_t timestamp_ms, char* buffer, size_t buffer_size) {
    time_t raw_time = (time_t)(timestamp_ms / 1000);
    int milliseconds = timestamp_ms % 1000;
    
    // 转换为本地时间
    struct tm *time_info = localtime(&raw_time);
    
    // 格式化为字符串
    strftime(buffer, buffer_size, "%Y-%m-%d %H:%M:%S", time_info);
    
    // 添加毫秒部分
    size_t len = strlen(buffer);
    snprintf(buffer + len, buffer_size - len, ".%03d", milliseconds);
}



// FilePath: /l:/work/dev/common/src/common_service.c
bool execute_command(const char *command, unsigned int timeout_ms, int need_output, char **output) 
{
    if (command == NULL || *command == '\0') {
        printf("%s: 命令参数无效(NULL或空)", __func__);
        return false;
    }

    // 初始化输出参数
    if (need_output && output) *output = NULL;

    // 创建管道（仅当需要输出时）
    int pipefd[2] = { -1, -1 };
    if (need_output && pipe(pipefd) == -1) {
        printf("%s: 创建管道失败: %s", __func__, strerror(errno));
        return false;
    }

    pid_t pid = fork();
    if (pid < 0) {
        printf("%s: fork失败: %s", __func__, strerror(errno));
        if (pipefd[0] != -1) close(pipefd[0]);
        if (pipefd[1] != -1) close(pipefd[1]);
        return false;
    }

    // 子进程执行命令
    if (pid == 0) {
        // 处理输出重定向
        if (need_output) {
            close(pipefd[0]); // 关闭读端
            dup2(pipefd[1], STDOUT_FILENO);
            dup2(pipefd[1], STDERR_FILENO);
            close(pipefd[1]);
        } else {
            // 不需要输出时重定向到/dev/null
            int devnull = open("/dev/null", O_WRONLY);
            if (devnull != -1) {
                dup2(devnull, STDOUT_FILENO);
                dup2(devnull, STDERR_FILENO);
                close(devnull);
            }
        }

        // 执行命令
        execl("/bin/sh", "sh", "-c", command, (char *)NULL);
        _exit(127); // exec失败时退出码
    }

    // 父进程处理
    if (need_output) close(pipefd[1]); // 关闭写端

    bool success = false;
    int status = -1;
    unsigned int elapsed_ms = 0;
    const unsigned int poll_interval_ms = 10; // 轮询间隔(ms)

    // 处理命令输出（如果需要）
    if (need_output && output) {
        char buf[1024];
        ssize_t count;
        size_t total_size = 0;
        *output = calloc(1, 1); // 初始化为空字符串

        while (1) {
            // 非阻塞读取输出
            if ((count = read(pipefd[0], buf, sizeof(buf)-1)) > 0) {
                buf[count] = '\0';
                // 动态扩展缓冲区
                char *new_output = realloc(*output, total_size + count + 1);
                if (!new_output) {
                    printf("%s: 内存分配失败", __func__);
                    free(*output);
                    *output = NULL;
                    break;
                }
                *output = new_output;
                memcpy(*output + total_size, buf, count);
                total_size += count;
                (*output)[total_size] = '\0';
            } 
            else if (count == 0) { // 管道关闭
                break;
            }
            else if (errno != EAGAIN) { // 读取错误
                printf("%s: 读取管道错误: %s", __func__, strerror(errno));
                break;
            }

            // 检查子进程状态
            int ret = waitpid(pid, &status, WNOHANG);
            if (ret == pid) break; // 子进程已退出
            if (ret < 0 && errno != EINTR) break; // 等待出错

            // 处理超时
            if (timeout_ms > 0 && elapsed_ms >= timeout_ms) break;
            usleep(poll_interval_ms * 1000);
            elapsed_ms += poll_interval_ms;
        }
        close(pipefd[0]);
    }

    // 等待子进程结束（如果尚未结束）
    if (waitpid(pid, &status, 0) == pid) {
        success = WIFEXITED(status) && WEXITSTATUS(status) == 0;
    }

    // 处理超时
    if (timeout_ms > 0 && elapsed_ms >= timeout_ms) {
        kill(pid, SIGKILL);
        waitpid(pid, &status, 0);
        printf("%s: 命令执行超时(%ums): %s", __func__, timeout_ms, command);
        return false;
    }

    return success;
}


uint64_t get_system_timestamp(void) {
    struct timespec ts;
    clock_gettime(CLOCK_REALTIME, &ts);
    return (uint64_t)ts.tv_sec * 1000 + ts.tv_nsec / 1000000;
}


// 获取系统语言环境
char* get_system_language() {
    char* lang = getenv("LANG");
    if (lang == NULL) {
        return "zh_CN"; // 默认值
    }
    
    // 查找点号位置
    char* dot = strchr(lang, '.');
    if (dot != NULL) {
        size_t len = dot - lang;
        if (len == 5 || (len == 1 && strncmp(lang, "C", 1) == 0) || 
            (len == 5 && strncmp(lang, "POSIX", 5) == 0)) {
            // 有效的语言环境格式
            static char language[16];
            strncpy(language, lang, len);
            language[len] = '\0';
            return language;
        }
    }
    
    return "zh_CN"; // 默认值
}

/* pthread_setname_np有限制，只能记录15个字符，如果长度超过，则取前15字节  */
int ems_set_thread_name(pthread_t thread, const char *name)
{
#define THREAD_NAME_MAX_LEN 16
    char thread_name[THREAD_NAME_MAX_LEN];

    if(name == NULL) {
        return -1;
    }

    snprintf(thread_name, sizeof(thread_name), "%s", name);
    return pthread_setname_np(thread, thread_name);
}