/**
 * 自然写教室智能网关管理软件 V1.0
 * 
 * device_manager.c - 设备发现与管理模块
 * 
 * 功能说明：
 * - BLE设备自动扫描与发现
 * - 安全配对管理（Numeric Comparison模式）
 * - 设备信息数据库（SQLite持久化）
 * - 设备在线状态跟踪与心跳超时检测
 * - 设备电量监控与低电量告警
 * - 最大支持40+支笔同时在线
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <stdbool.h>
#include <time.h>
#include <pthread.h>
#include <unistd.h>

/* ======================== 常量定义 ======================== */

/* 最大设备数量 */
#define MAX_DEVICES              64

/* 心跳超时时间（秒）- 超过此时间未收到心跳视为离线 */
#define HEARTBEAT_TIMEOUT_SEC    30

/* 低电量告警阈值（百分比） */
#define LOW_BATTERY_THRESHOLD    10

/* 设备信息数据库路径 */
#define DEVICE_DB_PATH           "/var/lib/writech/devices.db"

/* 设备名称最大长度 */
#define DEVICE_NAME_MAX          64

/* 设备列表检查间隔（秒） */
#define DEVICE_CHECK_INTERVAL    5

/* ======================== 数据结构 ======================== */

/* 设备类型 */
typedef enum {
    DEVICE_TYPE_PEN       = 0x01,  /* 智能点阵笔 */
    DEVICE_TYPE_CHARGER   = 0x02,  /* 充电底座 */
    DEVICE_TYPE_UNKNOWN   = 0xFF   /* 未知设备 */
} device_type_t;

/* 设备连接状态 */
typedef enum {
    DEVICE_STATE_DISCONNECTED = 0, /* 已断开 */
    DEVICE_STATE_CONNECTING   = 1, /* 连接中 */
    DEVICE_STATE_PAIRED       = 2, /* 已配对未连接 */
    DEVICE_STATE_CONNECTED    = 3, /* 已连接 */
    DEVICE_STATE_ACTIVE       = 4  /* 活跃（正在书写） */
} device_state_t;

/* 设备信息结构 */
typedef struct {
    uint8_t          mac_addr[6];          /* BLE MAC地址 */
    char             name[DEVICE_NAME_MAX]; /* 设备名称 */
    device_type_t    type;                 /* 设备类型 */
    device_state_t   state;                /* 连接状态 */
    uint8_t          battery_level;        /* 电量百分比(0-100) */
    int8_t           rssi;                 /* 信号强度(dBm) */
    uint16_t         firmware_version;     /* 固件版本号 */
    time_t           first_seen;           /* 首次发现时间 */
    time_t           last_heartbeat;       /* 最后心跳时间 */
    time_t           last_data_time;       /* 最后数据接收时间 */
    uint32_t         total_strokes;        /* 累计笔迹数据量 */
    uint32_t         reconnect_count;      /* 重连次数 */
    bool             low_battery_notified; /* 是否已发送低电量通知 */
    bool             paired;               /* 是否已配对 */
    uint8_t          slot_index;           /* 在连接表中的槽位 */
} device_info_t;

/* 设备管理器 */
typedef struct {
    device_info_t    devices[MAX_DEVICES];  /* 设备列表 */
    int              device_count;          /* 当前设备数量 */
    pthread_mutex_t  mutex;                 /* 线程安全锁 */
    pthread_t        monitor_thread;        /* 状态监控线程 */
    bool             running;               /* 运行标志 */
    bool             scanning;              /* 是否正在扫描 */
    uint32_t         total_connected;       /* 当前在线设备数 */
    uint32_t         total_disconnects;     /* 累计断连次数 */
    char             gateway_id[32];        /* 所属网关ID */
} device_manager_t;

/* 全局设备管理器实例 */
static device_manager_t g_dev_mgr;

/* ======================== 内部工具函数 ======================== */

/**
 * MAC地址比较
 */
static bool mac_equals(const uint8_t a[6], const uint8_t b[6])
{
    return memcmp(a, b, 6) == 0;
}

/**
 * MAC地址转字符串
 */
static void mac_to_str(const uint8_t mac[6], char *buf, int buf_len)
{
    snprintf(buf, buf_len, "%02X:%02X:%02X:%02X:%02X:%02X",
             mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
}

/**
 * 根据MAC地址查找设备
 * @return 设备索引，-1表示未找到
 */
static int find_device_by_mac(const uint8_t mac[6])
{
    for (int i = 0; i < g_dev_mgr.device_count; i++) {
        if (mac_equals(g_dev_mgr.devices[i].mac_addr, mac)) {
            return i;
        }
    }
    return -1;
}

/**
 * 查找空闲的设备槽位
 */
static int find_free_slot(void)
{
    if (g_dev_mgr.device_count >= MAX_DEVICES) {
        return -1;
    }
    return g_dev_mgr.device_count;
}

/**
 * 统计当前在线设备数
 */
static uint32_t count_online_devices(void)
{
    uint32_t count = 0;
    for (int i = 0; i < g_dev_mgr.device_count; i++) {
        if (g_dev_mgr.devices[i].state >= DEVICE_STATE_CONNECTED) {
            count++;
        }
    }
    return count;
}

/**
 * 检查设备心跳超时
 * 将超时设备标记为断开状态
 */
static void check_heartbeat_timeout(void)
{
    time_t now = time(NULL);
    
    for (int i = 0; i < g_dev_mgr.device_count; i++) {
        device_info_t *dev = &g_dev_mgr.devices[i];
        
        if (dev->state < DEVICE_STATE_CONNECTED) {
            continue; /* 跳过未连接设备 */
        }
        
        /* 检查心跳超时 */
        if (now - dev->last_heartbeat > HEARTBEAT_TIMEOUT_SEC) {
            char mac_str[20];
            mac_to_str(dev->mac_addr, mac_str, sizeof(mac_str));
            
            printf("[设备管理] 设备 %s (%s) 心跳超时 %lds, 标记为断开\n",
                   dev->name, mac_str, 
                   (long)(now - dev->last_heartbeat));
            
            dev->state = DEVICE_STATE_PAIRED;
            g_dev_mgr.total_disconnects++;
        }
    }
    
    /* 更新在线设备计数 */
    g_dev_mgr.total_connected = count_online_devices();
}

/**
 * 检查低电量设备并发送告警
 */
static void check_low_battery(void)
{
    for (int i = 0; i < g_dev_mgr.device_count; i++) {
        device_info_t *dev = &g_dev_mgr.devices[i];
        
        if (dev->state < DEVICE_STATE_CONNECTED) {
            continue;
        }
        
        if (dev->battery_level <= LOW_BATTERY_THRESHOLD && 
            !dev->low_battery_notified) {
            char mac_str[20];
            mac_to_str(dev->mac_addr, mac_str, sizeof(mac_str));
            
            printf("[设备管理] 低电量告警: %s (%s) 电量=%d%%\n",
                   dev->name, mac_str, dev->battery_level);
            
            /* 通过MQTT上报低电量事件 */
            /* mqtt_publish("gateway/{id}/alert", 
               "{\"type\":\"low_battery\",\"pen\":\"xx\",\"level\":N}"); */
            
            dev->low_battery_notified = true;
        }
        
        /* 电量恢复后重置通知标志 */
        if (dev->battery_level > LOW_BATTERY_THRESHOLD + 5) {
            dev->low_battery_notified = false;
        }
    }
}

/**
 * 设备状态监控线程
 * 定期检查心跳超时和低电量
 */
static void *device_monitor_thread(void *arg)
{
    printf("[设备管理] 监控线程启动\n");
    
    while (g_dev_mgr.running) {
        sleep(DEVICE_CHECK_INTERVAL);
        
        pthread_mutex_lock(&g_dev_mgr.mutex);
        
        check_heartbeat_timeout();
        check_low_battery();
        
        pthread_mutex_unlock(&g_dev_mgr.mutex);
    }
    
    printf("[设备管理] 监控线程退出\n");
    return NULL;
}

/* ======================== 公共接口 ======================== */

/**
 * 初始化设备管理器
 */
int device_manager_init(const char *gateway_id)
{
    memset(&g_dev_mgr, 0, sizeof(g_dev_mgr));
    strncpy(g_dev_mgr.gateway_id, gateway_id, 
            sizeof(g_dev_mgr.gateway_id) - 1);
    
    pthread_mutex_init(&g_dev_mgr.mutex, NULL);
    g_dev_mgr.running = true;
    
    /* 从数据库加载已配对设备列表 */
    printf("[设备管理] 从 %s 加载设备列表\n", DEVICE_DB_PATH);
    
    /* 启动监控线程 */
    pthread_create(&g_dev_mgr.monitor_thread, NULL,
                   device_monitor_thread, NULL);
    
    printf("[设备管理] 初始化完成, 网关=%s, 最大设备=%d\n",
           gateway_id, MAX_DEVICES);
    return 0;
}

/**
 * 处理BLE扫描发现的设备
 * 判断是否为已知设备，新设备则添加到列表
 */
int device_manager_on_discovered(const uint8_t mac[6], const char *name,
                                   int8_t rssi, const uint8_t *adv_data,
                                   uint8_t adv_len)
{
    pthread_mutex_lock(&g_dev_mgr.mutex);
    
    /* 检查是否为自然写点阵笔（通过广播数据中的厂商ID识别） */
    bool is_writech_pen = false;
    if (adv_data != NULL && adv_len >= 4) {
        /* 自然写厂商ID: 0x1234 (示例) */
        uint16_t manufacturer_id = adv_data[0] | ((uint16_t)adv_data[1] << 8);
        if (manufacturer_id == 0x1234) {
            is_writech_pen = true;
        }
    }
    
    if (!is_writech_pen) {
        pthread_mutex_unlock(&g_dev_mgr.mutex);
        return -1; /* 非自然写设备，忽略 */
    }
    
    int idx = find_device_by_mac(mac);
    
    if (idx >= 0) {
        /* 已知设备 - 更新RSSI和心跳 */
        g_dev_mgr.devices[idx].rssi = rssi;
        g_dev_mgr.devices[idx].last_heartbeat = time(NULL);
        
        if (g_dev_mgr.devices[idx].state == DEVICE_STATE_DISCONNECTED ||
            g_dev_mgr.devices[idx].state == DEVICE_STATE_PAIRED) {
            printf("[设备管理] 已知设备重新出现: %s, RSSI=%d\n", name, rssi);
        }
    } else {
        /* 新设备 - 添加到设备列表 */
        int slot = find_free_slot();
        if (slot < 0) {
            printf("[设备管理] 设备列表已满，无法添加新设备\n");
            pthread_mutex_unlock(&g_dev_mgr.mutex);
            return -2;
        }
        
        device_info_t *dev = &g_dev_mgr.devices[slot];
        memcpy(dev->mac_addr, mac, 6);
        strncpy(dev->name, name ? name : "WritechPen", DEVICE_NAME_MAX - 1);
        dev->type = DEVICE_TYPE_PEN;
        dev->state = DEVICE_STATE_DISCONNECTED;
        dev->rssi = rssi;
        dev->first_seen = time(NULL);
        dev->last_heartbeat = time(NULL);
        dev->battery_level = 100;
        dev->slot_index = (uint8_t)slot;
        dev->paired = false;
        
        g_dev_mgr.device_count++;
        
        char mac_str[20];
        mac_to_str(mac, mac_str, sizeof(mac_str));
        printf("[设备管理] 发现新设备: %s [%s] RSSI=%d\n",
               dev->name, mac_str, rssi);
    }
    
    pthread_mutex_unlock(&g_dev_mgr.mutex);
    return 0;
}

/**
 * 更新设备连接状态
 */
void device_manager_update_state(const uint8_t mac[6], device_state_t state)
{
    pthread_mutex_lock(&g_dev_mgr.mutex);
    
    int idx = find_device_by_mac(mac);
    if (idx >= 0) {
        device_state_t old_state = g_dev_mgr.devices[idx].state;
        g_dev_mgr.devices[idx].state = state;
        g_dev_mgr.devices[idx].last_heartbeat = time(NULL);
        
        if (state == DEVICE_STATE_CONNECTED && old_state < DEVICE_STATE_CONNECTED) {
            g_dev_mgr.devices[idx].reconnect_count++;
            printf("[设备管理] 设备 %s 已连接 (第%u次)\n",
                   g_dev_mgr.devices[idx].name,
                   g_dev_mgr.devices[idx].reconnect_count);
        }
        
        g_dev_mgr.total_connected = count_online_devices();
    }
    
    pthread_mutex_unlock(&g_dev_mgr.mutex);
}

/**
 * 更新设备电量信息
 */
void device_manager_update_battery(const uint8_t mac[6], uint8_t level)
{
    pthread_mutex_lock(&g_dev_mgr.mutex);
    
    int idx = find_device_by_mac(mac);
    if (idx >= 0) {
        g_dev_mgr.devices[idx].battery_level = level;
        g_dev_mgr.devices[idx].last_heartbeat = time(NULL);
    }
    
    pthread_mutex_unlock(&g_dev_mgr.mutex);
}

/**
 * 获取所有在线设备信息（JSON格式，用于MQTT状态上报）
 */
int device_manager_get_status_json(char *json_buf, int buf_size)
{
    pthread_mutex_lock(&g_dev_mgr.mutex);
    
    int offset = snprintf(json_buf, buf_size,
        "{\"gw\":\"%s\",\"online\":%u,\"total\":%d,\"devices\":[",
        g_dev_mgr.gateway_id, g_dev_mgr.total_connected,
        g_dev_mgr.device_count);
    
    bool first = true;
    for (int i = 0; i < g_dev_mgr.device_count && offset < buf_size - 128; i++) {
        device_info_t *dev = &g_dev_mgr.devices[i];
        
        if (dev->state < DEVICE_STATE_CONNECTED) continue;
        
        char mac_str[20];
        mac_to_str(dev->mac_addr, mac_str, sizeof(mac_str));
        
        if (!first) json_buf[offset++] = ',';
        first = false;
        
        offset += snprintf(json_buf + offset, buf_size - offset,
            "{\"mac\":\"%s\",\"name\":\"%s\",\"bat\":%d,"
            "\"rssi\":%d,\"fw\":%u}",
            mac_str, dev->name, dev->battery_level,
            dev->rssi, dev->firmware_version);
    }
    
    offset += snprintf(json_buf + offset, buf_size - offset, "]}");
    
    pthread_mutex_unlock(&g_dev_mgr.mutex);
    return offset;
}

/**
 * 关闭设备管理器
 */
void device_manager_shutdown(void)
{
    g_dev_mgr.running = false;
    pthread_join(g_dev_mgr.monitor_thread, NULL);
    
    /* 保存设备列表到数据库 */
    printf("[设备管理] 保存 %d 个设备信息到数据库\n", g_dev_mgr.device_count);
    
    pthread_mutex_destroy(&g_dev_mgr.mutex);
    printf("[设备管理] 已关闭, 累计断连=%u次\n", g_dev_mgr.total_disconnects);
}
