#include "unix_socket_server.h"
#include "mqtt_infor_handle.h"
#include "mylog.h"

#include <pthread.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/un.h>
#include <unistd.h>

#define IPC_SOCKET_PATH "/tmp/device_msg.sock"
#define IPC_BUFFER_SIZE 4096

static int s_ipc_server_fd = -1;
static pthread_t s_ipc_thread;
static int s_ipc_running = 0;

static void *ipc_server_thread(void *arg);

int ipc_start_unix_server(const char *socket_path) {
    if (s_ipc_running) {
        return 0;
    }

    const char *path = socket_path ? socket_path : IPC_SOCKET_PATH;

    s_ipc_server_fd = socket(AF_UNIX, SOCK_STREAM, 0);
    if (s_ipc_server_fd < 0) {
        my_zlog_error("unix socket 创建失败");
        return -1;
    }

    struct sockaddr_un addr;
    memset(&addr, 0, sizeof(addr));
    addr.sun_family = AF_UNIX;
    strncpy(addr.sun_path, path, sizeof(addr.sun_path) - 1);

    unlink(path);
    if (bind(s_ipc_server_fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
        my_zlog_error("unix socket 绑定失败");
        close(s_ipc_server_fd);
        s_ipc_server_fd = -1;
        return -1;
    }

    // 设置 socket 文件权限为 0777，允许所有用户读写
    if (chmod(path, 0777) < 0) {
        my_zlog_warn("设置 socket 文件权限失败");
    }

    if (listen(s_ipc_server_fd, 5) < 0) {
        my_zlog_error("unix socket 监听失败");
        close(s_ipc_server_fd);
        s_ipc_server_fd = -1;
        return -1;
    }

    s_ipc_running = 1;
    if (pthread_create(&s_ipc_thread, NULL, ipc_server_thread, (void *)path) != 0) {
        my_zlog_error("unix socket 线程创建失败");
        close(s_ipc_server_fd);
        s_ipc_server_fd = -1;
        s_ipc_running = 0;
        return -1;
    }

    my_zlog_info("IPC Unix socket 服务已启动: %s", path);
    return 0;
}

void ipc_stop_unix_server(void) {
    if (!s_ipc_running) return;

    s_ipc_running = 0;
    shutdown(s_ipc_server_fd, SHUT_RDWR);
    close(s_ipc_server_fd);
    s_ipc_server_fd = -1;
    pthread_join(s_ipc_thread, NULL);
}

static void *ipc_server_thread(void *arg) {
    char buffer[IPC_BUFFER_SIZE];

    while (s_ipc_running) {
        int client_fd = accept(s_ipc_server_fd, NULL, NULL);
        if (client_fd < 0) {
            if (s_ipc_running) {
                my_zlog_warn("IPC accept 失败");
            }
            continue;
        }

        ssize_t len = read(client_fd, buffer, sizeof(buffer) - 1);
        if (len > 0) {
            buffer[len] = '\0';
            cJSON *root = cJSON_Parse(buffer);
            if (root) {
                device_message_receive(root);
                cJSON_Delete(root);
            } else {
                my_zlog_warn("IPC 收到无效 JSON");
            }
        }

        close(client_fd);
    }

    return NULL;
}