/*
 * 自然写互动课堂教学管理网关软件 V1.0
 * ble_manager.c - BLE多连接管理器
 *
 * 功能说明：
 * 1. 基于BlueZ D-Bus接口的BLE多设备管理
 * 2. 自动扫描与连接自然写点阵笔（最多60支）
 * 3. GATT服务发现与特征值通知订阅
 * 4. BLE数据接收与分发
 * 5. 断线自动重连机制
 * 6. BLE适配器状态监控
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
#include <errno.h>
#include <syslog.h>

/* BlueZ D-Bus头文件 */
#include <bluetooth/bluetooth.h>
#include <bluetooth/hci.h>
#include <bluetooth/hci_lib.h>

/* 模块头文件 */
#include "ble_manager.h"
#include "ring_buffer.h"

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

/* 自然写笔GATT服务UUID */
#define PEN_SERVICE_UUID        "0000ffe0-0000-1000-8000-00805f9b34fb"

/* 笔迹数据特征值UUID */
#define STROKE_CHAR_UUID        "0000ffe1-0000-1000-8000-00805f9b34fb"

/* 最大同时连接设备数 */
#define MAX_BLE_CONNECTIONS     60

/* 扫描间隔（毫秒） */
#define SCAN_INTERVAL_MS        10000

/* 重连延迟（秒） */
#define RECONNECT_DELAY_SEC     5

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

/* BLE设备连接信息 */
typedef struct {
    char mac_address[18];           /* MAC地址 "AA:BB:CC:DD:EE:FF" */
    char device_name[64];           /* 设备名称 */
    int connection_handle;          /* 连接句柄 */
    int is_connected;               /* 是否已连接 */
    int is_subscribed;              /* 是否已订阅通知 */
    int gatt_handle;                /* GATT特征值句柄 */
    int rssi;                       /* 信号强度 */
    unsigned long last_data_time;   /* 最后收到数据的时间 */
    int reconnect_attempts;         /* 重连尝试次数 */
    char bound_student_id[32];      /* 绑定的学生ID */
} BLEDevice;

/* BLE管理器状态 */
typedef struct {
    int hci_dev_id;                 /* HCI设备ID */
    int hci_socket;                 /* HCI套接字 */
    int is_scanning;                /* 是否正在扫描 */
    int is_active;                  /* 管理器是否活跃 */
    BLEDevice devices[MAX_BLE_CONNECTIONS];  /* 设备列表 */
    int device_count;               /* 已连接设备数 */
    pthread_mutex_t mutex;          /* 线程安全锁 */
    pthread_t scan_thread;          /* 扫描线程 */
    pthread_t recv_thread;          /* 数据接收线程 */
    int event_pipe[2];              /* 事件通知管道 */
} BLEManager;

/* ========== 静态变量 ========== */

static BLEManager g_ble;

/* 数据回调函数指针 */
static void (*g_data_callback)(const char *mac, const uint8_t *data,
                                int len) = NULL;

/* ========== 初始化 ========== */

/**
 * 初始化BLE管理器
 * 打开HCI设备，配置扫描参数
 *
 * @return 0成功, -1失败
 */
int ble_manager_init(void) {
    memset(&g_ble, 0, sizeof(g_ble));
    pthread_mutex_init(&g_ble.mutex, NULL);

    /* 创建事件通知管道 */
    if (pipe(g_ble.event_pipe) < 0) {
        syslog(LOG_ERR, "BLE: 创建事件管道失败: %s", strerror(errno));
        return -1;
    }

    /* 打开默认HCI蓝牙适配器 */
    g_ble.hci_dev_id = hci_get_route(NULL);
    if (g_ble.hci_dev_id < 0) {
        syslog(LOG_ERR, "BLE: 未找到蓝牙适配器");
        return -1;
    }

    g_ble.hci_socket = hci_open_dev(g_ble.hci_dev_id);
    if (g_ble.hci_socket < 0) {
        syslog(LOG_ERR, "BLE: 打开HCI设备失败: %s", strerror(errno));
        return -1;
    }

    g_ble.is_active = 1;

    /* 启动扫描线程 */
    pthread_create(&g_ble.scan_thread, NULL, scan_thread_func, NULL);

    /* 启动数据接收线程 */
    pthread_create(&g_ble.recv_thread, NULL, recv_thread_func, NULL);

    syslog(LOG_INFO, "BLE管理器初始化完成，适配器ID=%d", g_ble.hci_dev_id);
    return 0;
}

/* ========== 设备扫描 ========== */

/**
 * 扫描线程函数
 * 周期性扫描BLE设备，发现新的自然写点阵笔后自动连接
 */
static void *scan_thread_func(void *arg) {
    (void)arg;

    syslog(LOG_INFO, "BLE: 扫描线程启动");

    while (g_ble.is_active) {
        /* 检查是否还有连接名额 */
        pthread_mutex_lock(&g_ble.mutex);
        int current_count = g_ble.device_count;
        pthread_mutex_unlock(&g_ble.mutex);

        if (current_count < MAX_BLE_CONNECTIONS) {
            /* 执行LE扫描 */
            perform_le_scan();
        }

        /* 检查需要重连的设备 */
        check_reconnect();

        /* 扫描间隔 */
        usleep(SCAN_INTERVAL_MS * 1000);
    }

    syslog(LOG_INFO, "BLE: 扫描线程退出");
    return NULL;
}

/**
 * 执行BLE低功耗扫描
 * 使用HCI LE扫描命令搜索附近的BLE设备
 */
static void perform_le_scan(void) {
    /* 设置LE扫描参数 */
    uint8_t scan_type = 0x01;           /* 主动扫描 */
    uint16_t scan_interval = 0x0010;    /* 扫描间隔 */
    uint16_t scan_window = 0x0010;      /* 扫描窗口 */
    uint8_t own_type = 0x00;            /* 公共地址 */
    uint8_t filter = 0x00;              /* 不过滤 */

    int ret = hci_le_set_scan_parameters(g_ble.hci_socket,
        scan_type, scan_interval, scan_window, own_type, filter, 1000);

    if (ret < 0) {
        syslog(LOG_WARNING, "BLE: 设置扫描参数失败");
        return;
    }

    /* 启动扫描 */
    ret = hci_le_set_scan_enable(g_ble.hci_socket, 0x01, 0x00, 1000);
    if (ret < 0) {
        syslog(LOG_WARNING, "BLE: 启动扫描失败");
        return;
    }

    g_ble.is_scanning = 1;

    /* 扫描持续3秒 */
    struct hci_filter flt;
    hci_filter_clear(&flt);
    hci_filter_set_ptype(HCI_EVENT_PKT, &flt);
    hci_filter_set_event(EVT_LE_META_EVENT, &flt);
    setsockopt(g_ble.hci_socket, SOL_HCI, HCI_FILTER, &flt, sizeof(flt));

    /* 读取扫描结果 */
    uint8_t buf[256];
    int scan_duration_ms = 3000;
    int elapsed = 0;

    while (elapsed < scan_duration_ms && g_ble.is_active) {
        struct timeval tv;
        tv.tv_sec = 0;
        tv.tv_usec = 100000;  /* 100ms超时 */

        fd_set rfds;
        FD_ZERO(&rfds);
        FD_SET(g_ble.hci_socket, &rfds);

        ret = select(g_ble.hci_socket + 1, &rfds, NULL, NULL, &tv);
        if (ret > 0) {
            int len = read(g_ble.hci_socket, buf, sizeof(buf));
            if (len > 0) {
                process_scan_result(buf, len);
            }
        }
        elapsed += 100;
    }

    /* 停止扫描 */
    hci_le_set_scan_enable(g_ble.hci_socket, 0x00, 0x00, 1000);
    g_ble.is_scanning = 0;
}

/**
 * 处理扫描结果
 * 解析广播包，筛选包含自然写服务UUID的设备
 */
static void process_scan_result(const uint8_t *data, int len) {
    if (len < 14) return;

    /* 解析HCI LE Meta事件 */
    evt_le_meta_event *meta = (evt_le_meta_event *)(data + 1 + HCI_EVENT_HDR_SIZE);
    if (meta->subevent != 0x02) return;  /* 非广播报告 */

    le_advertising_info *info = (le_advertising_info *)(meta->data + 1);

    /* 提取MAC地址 */
    char mac[18];
    ba2str(&info->bdaddr, mac);

    /* 检查是否已连接 */
    if (find_device_by_mac(mac) >= 0) {
        return;  /* 已连接，跳过 */
    }

    /* 检查广播数据中是否包含自然写服务UUID */
    if (check_service_uuid(info->data, info->length)) {
        syslog(LOG_INFO, "BLE: 发现自然写笔 %s", mac);
        /* 尝试连接 */
        connect_device(mac);
    }
}

/**
 * 检查广播数据中是否包含指定服务UUID
 */
static int check_service_uuid(const uint8_t *ad_data, int ad_len) {
    int offset = 0;
    while (offset < ad_len) {
        uint8_t field_len = ad_data[offset];
        if (field_len == 0) break;

        uint8_t field_type = ad_data[offset + 1];

        /* 0x06 或 0x07：128位服务UUID列表 */
        if ((field_type == 0x06 || field_type == 0x07) && field_len >= 17) {
            /* 比较UUID（简化：只比较前4字节特征值） */
            if (ad_data[offset + 2] == 0xFB &&
                ad_data[offset + 3] == 0x34 &&
                ad_data[offset + 4] == 0x9B &&
                ad_data[offset + 5] == 0x5F) {
                return 1;  /* 匹配自然写服务UUID */
            }
        }

        offset += field_len + 1;
    }
    return 0;
}

/* ========== 设备连接 ========== */

/**
 * 连接到指定MAC地址的BLE设备
 */
static int connect_device(const char *mac) {
    pthread_mutex_lock(&g_ble.mutex);

    if (g_ble.device_count >= MAX_BLE_CONNECTIONS) {
        pthread_mutex_unlock(&g_ble.mutex);
        return -1;
    }

    /* 查找空闲槽位 */
    int slot = -1;
    int i;
    for (i = 0; i < MAX_BLE_CONNECTIONS; i++) {
        if (!g_ble.devices[i].is_connected) {
            slot = i;
            break;
        }
    }

    if (slot < 0) {
        pthread_mutex_unlock(&g_ble.mutex);
        return -1;
    }

    /* 解析MAC地址 */
    bdaddr_t bdaddr;
    str2ba(mac, &bdaddr);

    /* 创建LE连接 */
    uint16_t handle = 0;
    int ret = hci_le_create_conn(g_ble.hci_socket,
        0x0060,     /* scan interval */
        0x0030,     /* scan window */
        0x00,       /* initiator filter */
        0x00,       /* peer addr type: public */
        bdaddr,     /* peer address */
        0x00,       /* own addr type */
        0x0028,     /* min conn interval */
        0x0038,     /* max conn interval */
        0x0000,     /* latency */
        0x002A,     /* supervision timeout */
        0x0000,     /* min CE length */
        0x0000,     /* max CE length */
        &handle, 10000);

    if (ret < 0) {
        syslog(LOG_WARNING, "BLE: 连接 %s 失败: %s", mac, strerror(errno));
        pthread_mutex_unlock(&g_ble.mutex);
        return -1;
    }

    /* 填充设备信息 */
    BLEDevice *dev = &g_ble.devices[slot];
    strncpy(dev->mac_address, mac, sizeof(dev->mac_address) - 1);
    dev->connection_handle = handle;
    dev->is_connected = 1;
    dev->reconnect_attempts = 0;
    dev->last_data_time = time(NULL);

    g_ble.device_count++;

    pthread_mutex_unlock(&g_ble.mutex);

    syslog(LOG_INFO, "BLE: 已连接 %s (handle=%d, 总数=%d)",
           mac, handle, g_ble.device_count);

    /* 发现GATT服务并订阅通知 */
    discover_and_subscribe(dev);

    return 0;
}

/* ========== GATT服务发现 ========== */

/**
 * 发现GATT服务并订阅笔迹数据通知
 */
static void discover_and_subscribe(BLEDevice *dev) {
    /* 简化实现：直接使用已知的特征值句柄 */
    /* 实际产品中需要完整的GATT服务发现流程 */
    dev->gatt_handle = 0x0025;  /* 笔迹数据特征值句柄 */

    /* 写入CCCD描述符启用通知（句柄+1是CCCD） */
    uint8_t enable_notify[] = {0x01, 0x00};
    struct bt_att_pdu pdu;
    pdu.opcode = BT_ATT_OP_WRITE_REQ;
    pdu.handle = dev->gatt_handle + 1;
    memcpy(pdu.data, enable_notify, 2);

    /* 发送ATT写请求 */
    /* hci_send_cmd(...) - 简化 */

    dev->is_subscribed = 1;
    syslog(LOG_INFO, "BLE: 已订阅 %s 的笔迹通知", dev->mac_address);
}

/* ========== 数据接收 ========== */

/**
 * 数据接收线程
 * 持续读取HCI事件，解析GATT通知中的笔迹数据
 */
static void *recv_thread_func(void *arg) {
    (void)arg;
    uint8_t buf[256];

    syslog(LOG_INFO, "BLE: 数据接收线程启动");

    while (g_ble.is_active) {
        int len = read(g_ble.hci_socket, buf, sizeof(buf));
        if (len <= 0) {
            usleep(1000);
            continue;
        }

        /* 解析HCI事件 */
        uint8_t event_type = buf[1];

        if (event_type == HCI_EVENT_PKT) {
            /* GATT通知数据 */
            process_gatt_notification(buf, len);
        } else if (event_type == EVT_DISCONN_COMPLETE) {
            /* 连接断开事件 */
            process_disconnect_event(buf, len);
        }
    }

    syslog(LOG_INFO, "BLE: 数据接收线程退出");
    return NULL;
}

/**
 * 处理GATT通知（笔迹数据）
 */
static void process_gatt_notification(const uint8_t *data, int len) {
    if (len < 10) return;

    /* 提取连接句柄 */
    uint16_t handle = data[4] | (data[5] << 8);

    /* 查找对应设备 */
    BLEDevice *dev = find_device_by_handle(handle);
    if (dev == NULL) return;

    /* 提取笔迹数据载荷 */
    const uint8_t *payload = data + 9;
    int payload_len = len - 9;

    dev->last_data_time = time(NULL);

    /* 将数据放入环形缓冲区（供协议转换器消费） */
    ring_buffer_write_with_header(dev->mac_address, payload, payload_len);

    /* 调用外部回调 */
    if (g_data_callback) {
        g_data_callback(dev->mac_address, payload, payload_len);
    }
}

/* ========== 辅助函数 ========== */

static int find_device_by_mac(const char *mac) {
    int i;
    for (i = 0; i < MAX_BLE_CONNECTIONS; i++) {
        if (g_ble.devices[i].is_connected &&
            strcmp(g_ble.devices[i].mac_address, mac) == 0) {
            return i;
        }
    }
    return -1;
}

static BLEDevice *find_device_by_handle(uint16_t handle) {
    int i;
    for (i = 0; i < MAX_BLE_CONNECTIONS; i++) {
        if (g_ble.devices[i].is_connected &&
            g_ble.devices[i].connection_handle == handle) {
            return &g_ble.devices[i];
        }
    }
    return NULL;
}

static void check_reconnect(void) {
    int i;
    time_t now = time(NULL);
    for (i = 0; i < MAX_BLE_CONNECTIONS; i++) {
        BLEDevice *dev = &g_ble.devices[i];
        if (!dev->is_connected && dev->mac_address[0] != '\0'
            && dev->reconnect_attempts < 10) {
            if (now - dev->last_data_time > RECONNECT_DELAY_SEC) {
                syslog(LOG_INFO, "BLE: 尝试重连 %s (第%d次)",
                       dev->mac_address, dev->reconnect_attempts + 1);
                connect_device(dev->mac_address);
                dev->reconnect_attempts++;
            }
        }
    }
}

/* ========== 外部接口 ========== */

int ble_manager_get_fd(void) { return g_ble.event_pipe[0]; }
int ble_manager_is_active(void) { return g_ble.is_active; }
int ble_manager_get_connected_count(void) { return g_ble.device_count; }

void ble_manager_process_events(void) {
    uint8_t dummy;
    read(g_ble.event_pipe[0], &dummy, 1);
}

void ble_manager_set_data_callback(void (*cb)(const char *, const uint8_t *, int)) {
    g_data_callback = cb;
}

void ble_manager_cleanup(void) {
    g_ble.is_active = 0;
    pthread_join(g_ble.scan_thread, NULL);
    pthread_join(g_ble.recv_thread, NULL);

    /* 断开所有设备 */
    int i;
    for (i = 0; i < MAX_BLE_CONNECTIONS; i++) {
        if (g_ble.devices[i].is_connected) {
            hci_disconnect(g_ble.hci_socket,
                           g_ble.devices[i].connection_handle, 0x13, 1000);
        }
    }

    close(g_ble.hci_socket);
    close(g_ble.event_pipe[0]);
    close(g_ble.event_pipe[1]);
    pthread_mutex_destroy(&g_ble.mutex);

    syslog(LOG_INFO, "BLE管理器已清理");
}
