#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <unistd.h>
#include <sys/file.h>
#include <fcntl.h>
#include <errno.h>
#include "log.h"
#include "channel_lock.h"   // 确保 CHANNEL_LOCK_FILE 定义在此

#define CHANNEL_LOCK_FILE "/var/run/lock/%s"

int get_std_file_str(const char *ori_name, char *out_filename, size_t out_size) {
    if (!ori_name || !out_filename || out_size < 1) {
        return -1;
    }

    int j = 0;
    int max_len = (int)(out_size - 1);

    // 1. 提取合法字符: 0-9, A-Z, a-z, _
    for (int i = 0; ori_name[i] != '\0' && j < max_len; i++) {
        unsigned char c = (unsigned char)ori_name[i];
        // isalnum() 检查是否是字母或数字
        out_filename[j++] = isalnum(c) ? c : '_';
    }
    out_filename[j] = '\0';
	if (j > 0) {
		return j;
	}

    int len = snprintf(out_filename, out_size, "unknown");

    // 检查是否截断
    if (len < 0 || len >= (int)out_size) {
        return -1; 
    }
    
    return len;
}


// 函数返回值：0成功，-1失败(通常是因为缓冲区太小)
int get_channel_file(const char *pathtemp, const char *ori_name, char *out_path, size_t out_size) {
    if (!ori_name || !out_path || !pathtemp || out_size == 0) {
        return -1;
    }

    char safe_str[256] = {0}; // 用于存放净化后的字符串

	int len = get_std_file_str(ori_name, safe_str, sizeof(safe_str));
    if (len < 0) {
    // 2. 组装路径
    // 注意：如果净化后的字符串为空，则使用一个默认名（如 "unknown"）
        strncpy(safe_str, "unknown", sizeof(safe_str) - 1);
        safe_str[sizeof(safe_str) - 1] = '\0';
    }
    
    int path_len = snprintf(out_path, out_size, pathtemp, safe_str);
    
    // 检查是否截断
    if (path_len < 0 || path_len >= (int)out_size) {
        return -1; 
    }
    
    return path_len;
}


/**
 * @brief 尝试获取设备的通道控制权
 * @return int 文件描述符，如果 >= 0 表示获取成功，可以进行初始化；-1 表示失败或已有进程在运行
 * @使用完毕后，需要通过关闭文件，来释放锁
 */
int try_acquire_channel_file_lock(const char *devno) {
    char filename[256];
    int ret = get_channel_file(CHANNEL_LOCK_FILE, devno, filename, sizeof(filename));
    if (ret <= 0) {
        SYSLOG(LOG_ERR, "try_acquire_channel_file_lock failed %s", devno);
        return -1;
    }

    int fd = open(filename, O_CREAT | O_RDWR, 0666);
    if (fd < 0) {
        SYSLOG(LOG_ERR, "try_acquire_channel_file_lock open lock file %s", devno);
        return -1;
    }

    // F_NBIO: 非阻塞模式。如果锁被别人持有，立刻返回错误，而不是挂起等待。
    // 这样我们可以立刻判断是该退出，还是该继续执行。
    if (flock(fd, LOCK_EX | LOCK_NB) < 0) {
        if (errno == EWOULDBLOCK) {
            // 锁已被其他进程持有, 正常场景
            close(fd);
            return -1; 
        } else {
            // 其他错误（如权限问题）
            SYSLOG(LOG_ERR, "try_acquire_channel_file_lock flock error %s", devno);
            close(fd);
            return -1;
        }
    }

    // --- 执行到这一步，说明本进程成功获取了锁 ---

    // 可选：记录当前进程ID到锁文件，方便调试
    char pid_str[16];
    int pid_len = snprintf(pid_str, sizeof(pid_str), "%d\n", getpid());
    ftruncate(fd, 0); // 清空文件
    write(fd, pid_str, pid_len);

    // 这里可以检查 CHANNEL_STATUS_FILE 来确认通道是否真的活跃
    // 但在本例中，获取锁即代表有权利建立连接
    return fd; 
}


