/*
 * 自然写互动课堂教学管理网关软件 V1.0
 * main.c - 网关主程序入口
 *
 * 功能说明：
 * 1. 系统初始化与模块启动协调
 * 2. 主事件循环（epoll事件驱动模型）
 * 3. 信号处理与优雅退出
 * 4. 系统运行状态监控
 *
 * 硬件平台：ARM Linux嵌入式网关
 * 角色：教室内BLE点阵笔 ↔ MQTT云平台的协议桥接
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <unistd.h>
#include <pthread.h>
#include <sys/epoll.h>
#include <sys/time.h>
#include <syslog.h>
#include <errno.h>

/* 模块头文件 */
#include "ble_manager.h"
#include "mqtt_client.h"
#include "protocol_converter.h"
#include "ring_buffer.h"
#include "offline_cache.h"
#include "device_manager.h"
#include "ota_updater.h"
#include "gateway_config.h"
#include "watchdog.h"
#include "http_server.h"

/* ========== 全局常量 ========== */

#define GATEWAY_VERSION         "1.0.0"
#define MAX_EPOLL_EVENTS        64
#define MAIN_LOOP_TIMEOUT_MS    100

/* ========== 全局变量 ========== */

/* 运行标志（信号处理中设置为0） */
static volatile int g_running = 1;

/* epoll文件描述符 */
static int g_epoll_fd = -1;

/* 系统启动时间 */
static struct timeval g_start_time;

/* 各模块状态 */
typedef struct {
    int ble_active;             /* BLE模块是否正常 */
    int mqtt_connected;         /* MQTT是否已连接 */
    int pen_count;              /* 已连接笔数量 */
    int cache_count;            /* 离线缓存数据条数 */
    unsigned long uptime_sec;   /* 运行时长（秒） */
    unsigned long total_packets;/* 累计转发数据包数 */
} GatewayStatus;

static GatewayStatus g_status;

/* ========== 信号处理 ========== */

/**
 * 信号处理函数
 * 捕获SIGINT/SIGTERM实现优雅退出
 */
static void signal_handler(int signo) {
    if (signo == SIGINT || signo == SIGTERM) {
        syslog(LOG_INFO, "收到终止信号 %d，准备退出...", signo);
        g_running = 0;
    }
}

/**
 * 注册信号处理器
 */
static void setup_signals(void) {
    struct sigaction sa;
    memset(&sa, 0, sizeof(sa));
    sa.sa_handler = signal_handler;
    sigemptyset(&sa.sa_mask);
    sa.sa_flags = 0;

    sigaction(SIGINT, &sa, NULL);
    sigaction(SIGTERM, &sa, NULL);

    /* 忽略SIGPIPE（网络连接断开时避免进程退出） */
    signal(SIGPIPE, SIG_IGN);
}

/* ========== 模块初始化 ========== */

/**
 * 初始化所有功能模块
 * 按依赖顺序逐一启动各子系统
 *
 * @return 0成功, -1失败
 */
static int init_modules(void) {
    syslog(LOG_INFO, "=== 自然写网关 V%s 启动 ===", GATEWAY_VERSION);

    /* 步骤1：加载配置文件 */
    if (gateway_config_load("/etc/writech/gateway.conf") != 0) {
        syslog(LOG_WARNING, "配置文件加载失败，使用默认配置");
        gateway_config_load_defaults();
    }

    /* 步骤2：初始化环形缓冲区（用于BLE→MQTT数据转发） */
    ring_buffer_init(64 * 1024);  /* 64KB缓冲区 */

    /* 步骤3：初始化离线缓存（SQLite） */
    if (offline_cache_init("/var/lib/writech/cache.db") != 0) {
        syslog(LOG_ERR, "离线缓存初始化失败");
        return -1;
    }

    /* 步骤4：初始化BLE管理器 */
    if (ble_manager_init() != 0) {
        syslog(LOG_ERR, "BLE管理器初始化失败");
        return -1;
    }

    /* 步骤5：初始化MQTT客户端 */
    const char *mqtt_host = gateway_config_get_string("mqtt.host", "mqtt.writech.com");
    int mqtt_port = gateway_config_get_int("mqtt.port", 8883);
    if (mqtt_client_init(mqtt_host, mqtt_port) != 0) {
        syslog(LOG_ERR, "MQTT客户端初始化失败");
        return -1;
    }

    /* 步骤6：初始化协议转换器 */
    protocol_converter_init();

    /* 步骤7：初始化设备管理器 */
    device_manager_init();

    /* 步骤8：初始化OTA升级模块 */
    ota_updater_init();

    /* 步骤9：初始化看门狗 */
    watchdog_init(30);  /* 30秒超时 */

    /* 步骤10：启动本地Web管理页面 */
    int http_port = gateway_config_get_int("http.port", 8080);
    http_server_start(http_port);

    syslog(LOG_INFO, "所有模块初始化完成");
    return 0;
}

/* ========== 主事件循环 ========== */

/**
 * 创建epoll实例并注册各模块的文件描述符
 */
static int setup_epoll(void) {
    g_epoll_fd = epoll_create1(0);
    if (g_epoll_fd < 0) {
        syslog(LOG_ERR, "epoll_create失败: %s", strerror(errno));
        return -1;
    }

    /* 注册BLE事件文件描述符 */
    int ble_fd = ble_manager_get_fd();
    if (ble_fd >= 0) {
        struct epoll_event ev;
        ev.events = EPOLLIN;
        ev.data.fd = ble_fd;
        epoll_ctl(g_epoll_fd, EPOLL_CTL_ADD, ble_fd, &ev);
    }

    /* 注册MQTT事件文件描述符 */
    int mqtt_fd = mqtt_client_get_fd();
    if (mqtt_fd >= 0) {
        struct epoll_event ev;
        ev.events = EPOLLIN | EPOLLOUT;
        ev.data.fd = mqtt_fd;
        epoll_ctl(g_epoll_fd, EPOLL_CTL_ADD, mqtt_fd, &ev);
    }

    return 0;
}

/**
 * 处理epoll事件
 */
static void process_events(struct epoll_event *events, int count) {
    int i;
    for (i = 0; i < count; i++) {
        int fd = events[i].data.fd;

        if (fd == ble_manager_get_fd()) {
            /* BLE数据就绪，读取并转发 */
            ble_manager_process_events();
        } else if (fd == mqtt_client_get_fd()) {
            /* MQTT事件处理 */
            if (events[i].events & EPOLLIN) {
                mqtt_client_process_read();
            }
            if (events[i].events & EPOLLOUT) {
                mqtt_client_process_write();
            }
        }
    }
}

/**
 * 定时任务处理（每次主循环迭代执行）
 * 处理非事件驱动的周期性任务
 */
static void periodic_tasks(void) {
    static unsigned long tick_count = 0;
    tick_count++;

    /* 每秒执行一次 */
    if (tick_count % 10 == 0) {
        /* 喂看门狗 */
        watchdog_feed();

        /* 更新运行时长 */
        struct timeval now;
        gettimeofday(&now, NULL);
        g_status.uptime_sec = now.tv_sec - g_start_time.tv_sec;
    }

    /* 每5秒执行一次 */
    if (tick_count % 50 == 0) {
        /* 更新状态信息 */
        g_status.ble_active = ble_manager_is_active();
        g_status.mqtt_connected = mqtt_client_is_connected();
        g_status.pen_count = ble_manager_get_connected_count();
        g_status.cache_count = offline_cache_get_count();
    }

    /* 每30秒执行一次 */
    if (tick_count % 300 == 0) {
        /* 尝试回传离线缓存数据 */
        if (g_status.mqtt_connected && g_status.cache_count > 0) {
            offline_cache_flush_to_mqtt();
        }

        /* 检查OTA更新 */
        ota_updater_check();
    }

    /* 协议转发：从环形缓冲区读取BLE数据，转换后发送到MQTT */
    protocol_converter_process();
}

/* ========== 清理退出 ========== */

/**
 * 清理并释放所有资源
 */
static void cleanup(void) {
    syslog(LOG_INFO, "开始清理资源...");

    http_server_stop();
    watchdog_stop();
    ota_updater_cleanup();
    device_manager_cleanup();
    mqtt_client_cleanup();
    ble_manager_cleanup();
    offline_cache_close();
    ring_buffer_destroy();
    gateway_config_free();

    if (g_epoll_fd >= 0) {
        close(g_epoll_fd);
    }

    syslog(LOG_INFO, "=== 网关已安全退出 ===");
    closelog();
}

/* ========== 主函数 ========== */

int main(int argc, char *argv[]) {
    /* 打开系统日志 */
    openlog("writech-gateway", LOG_PID | LOG_NDELAY, LOG_DAEMON);

    /* 记录启动时间 */
    gettimeofday(&g_start_time, NULL);
    memset(&g_status, 0, sizeof(g_status));

    /* 注册信号处理 */
    setup_signals();

    /* 初始化所有模块 */
    if (init_modules() != 0) {
        syslog(LOG_ERR, "模块初始化失败，退出");
        cleanup();
        return EXIT_FAILURE;
    }

    /* 设置epoll */
    if (setup_epoll() != 0) {
        cleanup();
        return EXIT_FAILURE;
    }

    /* 主事件循环 */
    struct epoll_event events[MAX_EPOLL_EVENTS];

    syslog(LOG_INFO, "进入主事件循环...");

    while (g_running) {
        int nfds = epoll_wait(g_epoll_fd, events, MAX_EPOLL_EVENTS,
                              MAIN_LOOP_TIMEOUT_MS);

        if (nfds < 0) {
            if (errno == EINTR) continue;
            syslog(LOG_ERR, "epoll_wait错误: %s", strerror(errno));
            break;
        }

        if (nfds > 0) {
            process_events(events, nfds);
        }

        periodic_tasks();
    }

    cleanup();
    return EXIT_SUCCESS;
}
