<script lang="ts" setup>
/**
 * 蓝牙设备测试页面
 * 功能：使用Web Bluetooth API连接和控制蓝牙设备
 * 支持：设备扫描、连接、数据通信、WiFi配置、自定义命令等
 */

// 页面布局配置
definePageMeta({
  layout: 'empty' // 使用空布局，不包含头部和底部
})

/**
 * 蓝牙设备状态管理
 * 用于跟踪蓝牙连接的各种状态信息
 */
const bluetoothState = ref({
  isSupported: false, // 浏览器是否支持Web Bluetooth API
  isConnected: false, // 是否已连接到设备
  isScanning: false, // 是否正在扫描设备
  devices: [] as BluetoothDevice[], // 发现的设备列表
  selectedDevice: null as BluetoothDevice | null, // 当前选中的设备
  server: null as BluetoothRemoteGATTServer | null, // GATT服务器连接
  service: null as BluetoothRemoteGATTService | null, // 目标服务
  characteristic: null as BluetoothRemoteGATTCharacteristic | null, // 通用特征值
  writeCharacteristic: null as BluetoothRemoteGATTCharacteristic | null, // 写入特征值
  readCharacteristic: null as BluetoothRemoteGATTCharacteristic | null // 读取特征值
})

/**
 * 设备信息管理
 * 存储连接设备的基本信息和状态
 */
const deviceInfo = ref({
  name: '', // 设备名称
  id: '', // 设备唯一标识符
  connected: false, // 连接状态
  batteryLevel: 0, // 电池电量百分比
  signalStrength: 0, // 信号强度
  firmwareVersion: '', // 固件版本
  deviceType: '', // 设备类型
  services: [] as string[] // 设备支持的服务列表
})

/**
 * 控制命令管理
 * 存储各种设备控制命令的参数
 */
const controlCommands = ref({
  ledOn: false, // LED开关状态
  motorSpeed: 0, // 电机速度 (0-100)
  temperature: 0, // 温度设置 (0-50°C)
  humidity: 0, // 湿度设置 (0-100%)
  wifiSsid: '', // WiFi网络名称
  wifiPassword: '', // WiFi密码
  customData: '' // 自定义数据命令
})

/**
 * 设备配置管理
 * 存储蓝牙设备的服务UUID和通信配置
 */
const deviceConfig = ref({
  serviceUuid: '000000ff-0000-1000-8000-00805f9b34fb', // 主服务UUID (小写格式)
  writeUuid: '0000ff01-0000-1000-8000-00805f9b34fb', // 写入特征值UUID
  readUuid: '0000ff02-0000-1000-8000-00805f9b34fb', // 读取特征值UUID
  sequenceControl: 0, // 序列号控制
  isEncrypted: false, // 是否启用加密
  isChecksum: true // 是否启用校验和
})

/**
 * 日志信息管理
 * 存储操作日志，用于调试和状态跟踪
 */
const logs = ref<string[]>([])

/**
 * 页面初始化
 * 检查浏览器对Web Bluetooth API的支持情况
 */
onMounted(() => {
  // 检查浏览器是否支持Web Bluetooth API
  bluetoothState.value.isSupported = 'bluetooth' in navigator
  
  if (!bluetoothState.value.isSupported) {
    addLog('浏览器不支持Web Bluetooth API')
  } else {
    addLog('Web Bluetooth API 支持正常')
  }
})

/**
 * 添加日志记录
 * @param message 日志消息内容
 * 功能：将操作日志添加到日志列表，包含时间戳，最多保留50条记录
 */
const addLog = (message: string) => {
  const timestamp = new Date().toLocaleTimeString() // 获取当前时间
  logs.value.unshift(`[${timestamp}] ${message}`) // 将新日志添加到列表开头
  
  // 限制日志数量，避免内存占用过多
  if (logs.value.length > 50) {
    logs.value = logs.value.slice(0, 50)
  }
}

/**
 * 扫描所有蓝牙设备
 * 功能：扫描附近所有可用的蓝牙设备，不限制服务类型
 */
const scanDevices = async () => {
  // 检查浏览器支持
  if (!bluetoothState.value.isSupported) {
    addLog('浏览器不支持蓝牙')
    return
  }

  try {
    bluetoothState.value.isScanning = true
    addLog('开始扫描蓝牙设备...')

    // 请求设备选择，接受所有设备类型
    const device = await navigator.bluetooth.requestDevice({
      acceptAllDevices: true, // 接受所有设备
      optionalServices: [
        'battery_service',      // 电池服务
        'device_information',   // 设备信息服务
        'generic_access'        // 通用访问服务
      ]
    })

    if (device) {
      // 保存选中的设备信息
      bluetoothState.value.selectedDevice = device
      deviceInfo.value.name = device.name || '未知设备'
      deviceInfo.value.id = device.id
      addLog(`发现设备: ${deviceInfo.value.name}`)
      
      // 监听设备断开连接事件
      device.addEventListener('gattserverdisconnected', onDeviceDisconnected)
    }
  } catch (error) {
    addLog(`扫描失败: ${error}`)
  } finally {
    bluetoothState.value.isScanning = false
  }
}

/**
 * 扫描特定服务设备
 * 功能：只扫描包含指定服务的蓝牙设备，用于精确匹配目标设备
 */
const scanSpecificService = async () => {
  // 检查浏览器支持
  if (!bluetoothState.value.isSupported) {
    addLog('浏览器不支持蓝牙')
    return
  }

  try {
    bluetoothState.value.isScanning = true
    addLog('开始扫描特定服务设备...')

    // 请求设备选择，只显示包含指定服务的设备
    const device = await navigator.bluetooth.requestDevice({
      filters: [
        { services: [deviceConfig.value.serviceUuid] } // 过滤条件：包含指定服务
      ],
      optionalServices: [
        'battery_service',      // 电池服务
        'device_information',   // 设备信息服务
        'generic_access'        // 通用访问服务
      ]
    })

    if (device) {
      // 保存选中的设备信息
      bluetoothState.value.selectedDevice = device
      deviceInfo.value.name = device.name || '未知设备'
      deviceInfo.value.id = device.id
      addLog(`发现设备: ${deviceInfo.value.name}`)
      
      // 监听设备断开连接事件
      device.addEventListener('gattserverdisconnected', onDeviceDisconnected)
    }
  } catch (error) {
    addLog(`扫描特定服务失败: ${error}`)
  } finally {
    bluetoothState.value.isScanning = false
  }
}

/**
 * 连接蓝牙设备
 * 功能：建立与选中设备的GATT连接，并初始化设备服务
 */
const connectDevice = async () => {
  // 检查是否已选择设备
  if (!bluetoothState.value.selectedDevice) {
    addLog('请先选择设备')
    return
  }

  try {
    addLog('正在连接设备...')
    
    // 建立GATT连接
    bluetoothState.value.server = await bluetoothState.value.selectedDevice.gatt?.connect()
    
    if (bluetoothState.value.server) {
      // 更新连接状态
      bluetoothState.value.isConnected = true
      deviceInfo.value.connected = true
      addLog('设备连接成功')
      
      // 初始化设备服务和特征值
      await initDevice()
    }
  } catch (error) {
    addLog(`连接失败: ${error}`)
  }
}

/**
 * 断开设备连接
 * 功能：主动断开与设备的连接
 */
const disconnectDevice = async () => {
  if (bluetoothState.value.server) {
    bluetoothState.value.server.disconnect()
    onDeviceDisconnected()
  }
}

/**
 * 设备断开连接处理
 * 功能：处理设备断开连接事件，清理相关状态和资源
 */
const onDeviceDisconnected = () => {
  // 重置连接状态
  bluetoothState.value.isConnected = false
  deviceInfo.value.connected = false
  
  // 清理连接资源
  bluetoothState.value.server = null
  bluetoothState.value.service = null
  bluetoothState.value.characteristic = null
  bluetoothState.value.writeCharacteristic = null
  bluetoothState.value.readCharacteristic = null
  
  addLog('设备已断开连接')
}

/**
 * 初始化设备
 * 功能：发现设备服务，获取特征值，启用数据通知，发送初始化命令
 */
const initDevice = async () => {
  if (!bluetoothState.value.server) return

  try {
    addLog('正在初始化设备...')
    
    // 获取设备的所有主要服务
    const services = await bluetoothState.value.server.getPrimaryServices()
    deviceInfo.value.services = services.map(s => s.uuid)
    addLog(`发现 ${services.length} 个服务`)
    
    // 打印所有服务UUID用于调试
    services.forEach((service, index) => {
      addLog(`服务 ${index + 1}: ${service.uuid}`)
    })
    
    // 查找目标服务（不区分大小写匹配）
    const targetService = services.find(s => 
      s.uuid.toLowerCase() === deviceConfig.value.serviceUuid.toLowerCase()
    )
    
    if (targetService) {
      bluetoothState.value.service = targetService
      addLog('找到目标服务')
      
      // 获取目标服务的所有特征值
      const characteristics = await targetService.getCharacteristics()
      addLog(`发现 ${characteristics.length} 个特征值`)
      
      // 打印所有特征值UUID用于调试
      characteristics.forEach((char, index) => {
        addLog(`特征值 ${index + 1}: ${char.uuid}`)
      })
      
      // 查找读写特征值（不区分大小写匹配）
      bluetoothState.value.writeCharacteristic = characteristics.find(c => 
        c.uuid.toLowerCase() === deviceConfig.value.writeUuid.toLowerCase()
      )
      bluetoothState.value.readCharacteristic = characteristics.find(c => 
        c.uuid.toLowerCase() === deviceConfig.value.readUuid.toLowerCase()
      )
      
      if (bluetoothState.value.writeCharacteristic) {
        addLog('找到写入特征值')
      }
      if (bluetoothState.value.readCharacteristic) {
        addLog('找到读取特征值')
        
        // 启用特征值通知，用于接收设备数据
        await bluetoothState.value.readCharacteristic.startNotifications()
        bluetoothState.value.readCharacteristic.addEventListener('characteristicvaluechanged', onCharacteristicValueChanged)
        addLog('已启用数据通知')
      }
      
      // 获取设备基本信息（如电池电量）
      await getDeviceInfo()
      
      // 发送初始化命令获取固件版本
      await sendCustomData('get_fw')
    } else {
      addLog('未找到目标服务，尝试获取设备基本信息')
      await getDeviceInfo()
      
      // 如果没有目标服务，尝试使用通用访问服务进行通信
      const genericAccessService = services.find(s => s.uuid === '00001800-0000-1000-8000-00805f9b34fb')
      if (genericAccessService) {
        addLog('找到通用访问服务，尝试获取特征值')
        const characteristics = await genericAccessService.getCharacteristics()
        
        // 打印通用访问服务的特征值
        characteristics.forEach((char, index) => {
          addLog(`通用访问特征值 ${index + 1}: ${char.uuid}`)
        })
        
        // 查找可写的特征值
        const writableChars = characteristics.filter(c => c.properties.write || c.properties.writeWithoutResponse)
        if (writableChars.length > 0) {
          bluetoothState.value.writeCharacteristic = writableChars[0]
          addLog(`使用通用访问服务的写入特征值: ${writableChars[0].uuid}`)
        }
        
        // 查找可读的特征值
        const readableChars = characteristics.filter(c => c.properties.read || c.properties.notify)
        if (readableChars.length > 0) {
          bluetoothState.value.readCharacteristic = readableChars[0]
          addLog(`使用通用访问服务的读取特征值: ${readableChars[0].uuid}`)
          
          // 尝试读取设备名称
          const deviceNameChar = characteristics.find(c => c.uuid === '00002a00-0000-1000-8000-00805f9b34fb')
          if (deviceNameChar && deviceNameChar.properties.read) {
            try {
              const deviceNameValue = await deviceNameChar.readValue()
              const deviceName = String.fromCharCode(...new Uint8Array(deviceNameValue.buffer))
              deviceInfo.value.name = deviceName
              addLog(`读取设备名称: ${deviceName}`)
            } catch (readError) {
              addLog(`读取设备名称失败: ${readError}`)
            }
          }
          
          // 尝试读取外观信息
          const appearanceChar = characteristics.find(c => c.uuid === '00002a01-0000-1000-8000-00805f9b34fb')
          if (appearanceChar && appearanceChar.properties.read) {
            try {
              const appearanceValue = await appearanceChar.readValue()
              const appearance = new DataView(appearanceValue.buffer).getUint16(0, true)
              addLog(`设备外观: 0x${appearance.toString(16)}`)
            } catch (readError) {
              addLog(`读取设备外观失败: ${readError}`)
            }
          }
          
          // 尝试启用通知（如果支持）
          if (readableChars[0].properties.notify) {
            try {
              await bluetoothState.value.readCharacteristic.startNotifications()
              bluetoothState.value.readCharacteristic.addEventListener('characteristicvaluechanged', onCharacteristicValueChanged)
              addLog('已启用通用访问服务的数据通知')
            } catch (notifyError) {
              addLog('无法启用通用访问服务的数据通知')
            }
          } else {
            addLog('该特征值不支持通知功能')
          }
        }
      }
    }
  } catch (error) {
    addLog(`设备初始化失败: ${error}`)
  }
}

/**
 * 特征值变化处理
 * 功能：处理从设备接收到的数据，解析并显示相关信息
 * @param event 特征值变化事件
 */
const onCharacteristicValueChanged = (event: Event) => {
  const characteristic = event.target as BluetoothRemoteGATTCharacteristic
  const value = characteristic.value
  
  if (value) {
    // 将接收到的数据转换为文本
    const data = new Uint8Array(value.buffer)
    const text = String.fromCharCode(...data)
    addLog(`收到数据: ${text}`)
    
    // 处理特定的设备响应
    if (text.includes('wifi_ok')) {
      addLog('WiFi连接成功')
    } else if (text.includes('wifi_err')) {
      addLog('WiFi连接失败')
    } else if (text.includes('fw_version')) {
      // 解析固件版本信息
      deviceInfo.value.firmwareVersion = text.replace('fw_version:', '')
      addLog(`固件版本: ${deviceInfo.value.firmwareVersion}`)
    }
  }
}

/**
 * 获取设备信息
 * 功能：读取设备的基本信息，如电池电量等
 */
const getDeviceInfo = async () => {
  if (!bluetoothState.value.server) return

  try {
    // 尝试获取电池服务并读取电池电量
    try {
      const batteryService = await bluetoothState.value.server.getPrimaryService('battery_service')
      const batteryCharacteristic = await batteryService.getCharacteristic('battery_level')
      const batteryValue = await batteryCharacteristic.readValue()
      deviceInfo.value.batteryLevel = batteryValue.getUint8(0)
      addLog(`电池电量: ${deviceInfo.value.batteryLevel}%`)
    } catch (batteryError) {
      addLog('设备不支持电池服务')
      deviceInfo.value.batteryLevel = 0
    }

    // 尝试获取设备信息服务
    try {
      const deviceInfoService = await bluetoothState.value.server.getPrimaryService('device_information')
      const characteristics = await deviceInfoService.getCharacteristics()
      
      // 尝试读取设备名称
      const deviceNameChar = characteristics.find(c => c.uuid === '00002a00-0000-1000-8000-00805f9b34fb')
      if (deviceNameChar) {
        const deviceNameValue = await deviceNameChar.readValue()
        const deviceName = String.fromCharCode(...new Uint8Array(deviceNameValue.buffer))
        addLog(`设备名称: ${deviceName}`)
      }
      
      // 尝试读取固件版本
      const firmwareChar = characteristics.find(c => c.uuid === '00002a26-0000-1000-8000-00805f9b34fb')
      if (firmwareChar) {
        const firmwareValue = await firmwareChar.readValue()
        const firmwareVersion = String.fromCharCode(...new Uint8Array(firmwareValue.buffer))
        deviceInfo.value.firmwareVersion = firmwareVersion
        addLog(`固件版本: ${firmwareVersion}`)
      }
    } catch (deviceInfoError) {
      addLog('设备不支持设备信息服务')
    }

  } catch (error) {
    addLog(`获取设备信息失败: ${error}`)
  }
}

/**
 * 发送数据到设备
 * 功能：通过写入特征值向设备发送数据
 * @param data 要发送的数据（Uint8Array格式）
 * @returns 发送是否成功
 */
const sendDataToDevice = async (data: Uint8Array) => {
  if (!bluetoothState.value.writeCharacteristic) {
    addLog('写入特征值不可用，尝试查找可写特征值')
    
    // 尝试查找其他可写的特征值
    if (bluetoothState.value.server) {
      try {
        const services = await bluetoothState.value.server.getPrimaryServices()
        for (const service of services) {
          const characteristics = await service.getCharacteristics()
          const writableChars = characteristics.filter(c => 
            c.properties.write || c.properties.writeWithoutResponse
          )
          
          if (writableChars.length > 0) {
            bluetoothState.value.writeCharacteristic = writableChars[0]
            addLog(`找到可写特征值: ${writableChars[0].uuid}`)
            break
          }
        }
      } catch (error) {
        addLog(`查找可写特征值失败: ${error}`)
        return false
      }
    }
    
    if (!bluetoothState.value.writeCharacteristic) {
      addLog('未找到任何可写的特征值，无法发送控制命令')
      addLog('提示：该设备可能不支持通过蓝牙进行控制，或者需要特定的服务UUID')
      return false
    }
  }

  try {
    // 通过写入特征值发送数据
    await bluetoothState.value.writeCharacteristic.writeValue(data)
    return true
  } catch (error) {
    addLog(`发送数据失败: ${error}`)
    return false
  }
}

/**
 * 字符串转ArrayBuffer
 * 功能：将字符串转换为ArrayBuffer格式，用于蓝牙数据传输
 * @param str 要转换的字符串
 * @returns ArrayBuffer格式的数据
 */
const stringToBuffer = (str: string): ArrayBuffer => {
  const bytes = new Uint8Array(str.length)
  for (let i = 0; i < str.length; i++) {
    bytes[i] = str.charCodeAt(i) // 将字符转换为ASCII码
  }
  return bytes.buffer
}

/**
 * 发送自定义数据
 * 功能：向设备发送自定义字符串数据
 * @param data 要发送的字符串数据
 */
const sendCustomData = async (data: string) => {
  if (!bluetoothState.value.isConnected) {
    addLog('设备未连接')
    return
  }

  try {
    // 将字符串转换为ArrayBuffer
    const buffer = stringToBuffer(data)
    const success = await sendDataToDevice(new Uint8Array(buffer))
    if (success) {
      addLog(`发送自定义数据: ${data}`)
    }
  } catch (error) {
    addLog(`发送自定义数据失败: ${error}`)
  }
}

/**
 * 发送WiFi配置
 * 功能：向设备发送WiFi网络配置信息（SSID和密码）
 */
const sendWiFiConfig = async () => {
  if (!bluetoothState.value.isConnected) {
    addLog('设备未连接')
    return
  }

  if (!controlCommands.value.wifiSsid || !controlCommands.value.wifiPassword) {
    addLog('请输入WiFi名称和密码')
    return
  }

  try {
    addLog('正在发送WiFi配置...')
    
    // 发送WiFi网络名称（SSID）
    const ssidBuffer = stringToBuffer(controlCommands.value.wifiSsid)
    await sendDataToDevice(new Uint8Array(ssidBuffer))
    
    // 发送WiFi密码
    const passwordBuffer = stringToBuffer(controlCommands.value.wifiPassword)
    await sendDataToDevice(new Uint8Array(passwordBuffer))
    
    addLog('WiFi配置发送完成')
  } catch (error) {
    addLog(`发送WiFi配置失败: ${error}`)
  }
}

/**
 * 发送控制命令
 * 功能：向设备发送各种控制命令，如LED、电机、温度、湿度等
 * @param command 命令类型
 * @param value 命令参数值
 */
const sendCommand = async (command: string, value?: number) => {
  if (!bluetoothState.value.isConnected) {
    addLog('设备未连接')
    return
  }

  try {
    let data: Uint8Array
    
    // 根据命令类型构造不同的数据包
    switch (command) {
      case 'led':
        // LED控制：0x01 + 状态(0x00关闭/0x01开启)
        data = new Uint8Array([0x01, value ? 0x01 : 0x00])
        addLog(`发送LED命令: ${value ? '开启' : '关闭'}`)
        break
      case 'motor':
        // 电机控制：0x02 + 速度值(0-100)
        data = new Uint8Array([0x02, value || 0])
        addLog(`发送电机速度: ${value}%`)
        break
      case 'temperature':
        // 温度控制：0x03 + 温度值(0-50)
        data = new Uint8Array([0x03, value || 0])
        addLog(`设置温度: ${value}°C`)
        break
      case 'humidity':
        // 湿度控制：0x04 + 湿度值(0-100)
        data = new Uint8Array([0x04, value || 0])
        addLog(`设置湿度: ${value}%`)
        break
      default:
        addLog(`未知命令: ${command}`)
        return
    }
    
    // 发送构造好的数据包
    await sendDataToDevice(data)
  } catch (error) {
    addLog(`发送命令失败: ${error}`)
  }
}

/**
 * 控制LED开关
 * 功能：切换LED灯的开关状态
 */
const toggleLED = () => {
  controlCommands.value.ledOn = !controlCommands.value.ledOn
  sendCommand('led', controlCommands.value.ledOn ? 1 : 0)
}

/**
 * 控制电机速度
 * 功能：设置电机运行速度
 * @param speed 电机速度 (0-100)
 */
const setMotorSpeed = (speed: number) => {
  controlCommands.value.motorSpeed = speed
  sendCommand('motor', speed)
}

/**
 * 设置温度
 * 功能：设置设备的目标温度
 * @param temp 目标温度 (0-50°C)
 */
const setTemperature = (temp: number) => {
  controlCommands.value.temperature = temp
  sendCommand('temperature', temp)
}

/**
 * 设置湿度
 * 功能：设置设备的目标湿度
 * @param humidity 目标湿度 (0-100%)
 */
const setHumidity = (humidity: number) => {
  controlCommands.value.humidity = humidity
  sendCommand('humidity', humidity)
}

/**
 * 发送自定义命令
 * 功能：发送用户输入的自定义数据命令
 */
const sendCustomCommand = () => {
  if (controlCommands.value.customData) {
    sendCustomData(controlCommands.value.customData)
  }
}

/**
 * 读取通用访问服务信息
 * 功能：读取通用访问服务的所有可用信息
 */
const readGenericAccessInfo = async () => {
  if (!bluetoothState.value.isConnected) {
    addLog('设备未连接')
    return
  }

  try {
    addLog('读取通用访问服务信息...')
    
    // 获取通用访问服务
    const genericAccessService = await bluetoothState.value.server.getPrimaryService('00001800-0000-1000-8000-00805f9b34fb')
    const characteristics = await genericAccessService.getCharacteristics()
    
    for (const char of characteristics) {
      addLog(`特征值: ${char.uuid}`)
      addLog(`属性: ${JSON.stringify(char.properties)}`)
      
      // 根据特征值UUID读取对应信息
      if (char.properties.read) {
        try {
          const value = await char.readValue()
          
          switch (char.uuid) {
            case '00002a00-0000-1000-8000-00805f9b34fb': // 设备名称
              const deviceName = String.fromCharCode(...new Uint8Array(value.buffer))
              deviceInfo.value.name = deviceName
              addLog(`设备名称: ${deviceName}`)
              break
              
            case '00002a01-0000-1000-8000-00805f9b34fb': // 外观
              const appearance = new DataView(value.buffer).getUint16(0, true)
              addLog(`设备外观: 0x${appearance.toString(16)}`)
              break
              
            case '00002a02-0000-1000-8000-00805f9b34fb': // 隐私标志
              const privacyFlag = new DataView(value.buffer).getUint8(0)
              addLog(`隐私标志: ${privacyFlag}`)
              break
              
            case '00002a03-0000-1000-8000-00805f9b34fb': // 重新连接地址
              const reconnectAddress = Array.from(new Uint8Array(value.buffer))
                .map(b => b.toString(16).padStart(2, '0'))
                .join(':')
              addLog(`重新连接地址: ${reconnectAddress}`)
              break
              
            case '00002a04-0000-1000-8000-00805f9b34fb': // 外设首选连接参数
              const params = new DataView(value.buffer)
              const minInterval = params.getUint16(0, true)
              const maxInterval = params.getUint16(2, true)
              const latency = params.getUint16(4, true)
              const timeout = params.getUint16(6, true)
              addLog(`连接参数: 最小间隔=${minInterval}ms, 最大间隔=${maxInterval}ms, 延迟=${latency}, 超时=${timeout}ms`)
              break
              
            case '00002aa6-0000-1000-8000-00805f9b34fb': // 中央地址解析
              const centralAddressResolution = new DataView(value.buffer).getUint8(0)
              addLog(`中央地址解析: ${centralAddressResolution ? '支持' : '不支持'}`)
              break
              
            default:
              // 其他特征值，尝试作为文本读取
              const text = String.fromCharCode(...new Uint8Array(value.buffer))
              addLog(`未知特征值数据: ${text}`)
              break
          }
        } catch (readError) {
          addLog(`读取特征值 ${char.uuid} 失败: ${readError}`)
        }
      }
    }
  } catch (error) {
    addLog(`读取通用访问服务信息失败: ${error}`)
  }
}

/**
 * 查找可写特征值
 * 功能：在所有服务中查找支持写入操作的特征值
 */
const findWritableCharacteristics = async () => {
  if (!bluetoothState.value.isConnected) {
    addLog('设备未连接')
    return
  }

  try {
    addLog('查找可写特征值...')
    
    const services = await bluetoothState.value.server.getPrimaryServices()
    const writableChars = []
    
    for (const service of services) {
      addLog(`检查服务: ${service.uuid}`)
      
      try {
        const characteristics = await service.getCharacteristics()
        
        for (const char of characteristics) {
          const properties = char.properties
          addLog(`特征值: ${char.uuid}`)
          addLog(`属性: ${JSON.stringify(properties)}`)
          
          // 检查是否支持写入
          if (properties.write || properties.writeWithoutResponse) {
            writableChars.push({
              serviceUuid: service.uuid,
              characteristicUuid: char.uuid,
              properties: properties
            })
            addLog(`✓ 找到可写特征值: ${char.uuid}`)
          }
          
          // 检查是否支持读取
          if (properties.read) {
            addLog(`✓ 找到可读特征值: ${char.uuid}`)
          }
          
          // 检查是否支持通知
          if (properties.notify) {
            addLog(`✓ 找到可通知特征值: ${char.uuid}`)
          }
        }
      } catch (charError) {
        addLog(`获取特征值失败: ${charError}`)
      }
    }
    
    if (writableChars.length > 0) {
      addLog(`共找到 ${writableChars.length} 个可写特征值:`)
      writableChars.forEach((char, index) => {
        addLog(`${index + 1}. 服务: ${char.serviceUuid}`)
        addLog(`   特征值: ${char.characteristicUuid}`)
        addLog(`   属性: ${JSON.stringify(char.properties)}`)
      })
      
      // 使用第一个可写特征值
      const firstWritable = writableChars[0]
      const service = await bluetoothState.value.server.getPrimaryService(firstWritable.serviceUuid)
      const characteristic = await service.getCharacteristic(firstWritable.characteristicUuid)
      bluetoothState.value.writeCharacteristic = characteristic
      addLog(`已设置写入特征值: ${firstWritable.characteristicUuid}`)
    } else {
      addLog('未找到任何可写的特征值')
      addLog('该设备可能不支持通过蓝牙进行控制')
    }
    
  } catch (error) {
    addLog(`查找可写特征值失败: ${error}`)
  }
}

/**
 * 尝试通用设备通信
 * 功能：当设备没有特定服务时，尝试使用通用方式进行通信
 */
const tryGenericCommunication = async () => {
  if (!bluetoothState.value.isConnected) {
    addLog('设备未连接')
    return
  }

  try {
    addLog('尝试通用设备通信...')
    
    // 首先读取通用访问服务信息
    await readGenericAccessInfo()
    
    // 查找可写特征值
    await findWritableCharacteristics()
    
    // 获取所有服务
    const services = await bluetoothState.value.server.getPrimaryServices()
    
    for (const service of services) {
      addLog(`检查服务: ${service.uuid}`)
      
      try {
        const characteristics = await service.getCharacteristics()
        
        for (const char of characteristics) {
          addLog(`特征值: ${char.uuid}, 属性: ${JSON.stringify(char.properties)}`)
          
          // 尝试读取可读的特征值
          if (char.properties.read) {
            try {
              const value = await char.readValue()
              const data = new Uint8Array(value.buffer)
              const text = String.fromCharCode(...data)
              addLog(`读取数据: ${text}`)
            } catch (readError) {
              addLog(`读取失败: ${readError}`)
            }
          }
          
          // 尝试启用通知
          if (char.properties.notify) {
            try {
              await char.startNotifications()
              char.addEventListener('characteristicvaluechanged', onCharacteristicValueChanged)
              addLog(`已启用通知: ${char.uuid}`)
            } catch (notifyError) {
              addLog(`启用通知失败: ${notifyError}`)
            }
          }
        }
      } catch (charError) {
        addLog(`获取特征值失败: ${charError}`)
      }
    }
  } catch (error) {
    addLog(`通用通信失败: ${error}`)
  }
}

/**
 * 清除日志
 * 功能：清空操作日志列表
 */
const clearLogs = () => {
  logs.value = []
}
</script>

<template>
  <div class="min-h-screen bg-gray-50 dark:bg-gray-900 p-4">
    <div class="max-w-6xl mx-auto">
      <!-- 页面标题 -->
      <div class="text-center mb-8">
        <h1 class="text-3xl font-bold text-gray-900 dark:text-white mb-2">
          蓝牙设备测试
        </h1>
        <p class="text-gray-600 dark:text-gray-300">
          Web Bluetooth API 设备连接与控制
        </p>
      </div>

      <!-- 支持状态 -->
      <div class="mb-6">
        <div class="bg-white dark:bg-gray-800 rounded-lg p-4 shadow-sm">
          <div class="flex items-center space-x-2">
            <div 
              class="w-3 h-3 rounded-full"
              :class="bluetoothState.isSupported ? 'bg-green-500' : 'bg-red-500'"
            ></div>
            <span class="text-sm font-medium text-gray-900 dark:text-white">
              Web Bluetooth API {{ bluetoothState.isSupported ? '支持' : '不支持' }}
            </span>
          </div>
        </div>
      </div>

      <div class="grid grid-cols-1 lg:grid-cols-2 gap-6">
        <!-- 设备控制面板 -->
        <div class="space-y-6">
          <!-- 设备扫描 -->
          <div class="bg-white dark:bg-gray-800 rounded-lg p-6 shadow-sm">
            <h2 class="text-xl font-semibold text-gray-900 dark:text-white mb-4">
              设备扫描
            </h2>
            <div class="space-y-4">
              <button
                @click="scanDevices"
                :disabled="bluetoothState.isScanning || !bluetoothState.isSupported"
                class="w-full px-4 py-2 bg-blue-600 hover:bg-blue-700 disabled:bg-gray-400 text-white font-medium rounded-lg transition-colors"
              >
                {{ bluetoothState.isScanning ? '扫描中...' : '扫描所有设备' }}
              </button>
              
              <button
                @click="scanSpecificService"
                :disabled="bluetoothState.isScanning || !bluetoothState.isSupported"
                class="w-full px-4 py-2 bg-indigo-600 hover:bg-indigo-700 disabled:bg-gray-400 text-white font-medium rounded-lg transition-colors"
              >
                {{ bluetoothState.isScanning ? '扫描中...' : '扫描特定服务设备' }}
              </button>
              
              <button
                @click="connectDevice"
                :disabled="!bluetoothState.selectedDevice || bluetoothState.isConnected"
                class="w-full px-4 py-2 bg-green-600 hover:bg-green-700 disabled:bg-gray-400 text-white font-medium rounded-lg transition-colors"
              >
                连接设备
              </button>
              
              <button
                @click="disconnectDevice"
                :disabled="!bluetoothState.isConnected"
                class="w-full px-4 py-2 bg-red-600 hover:bg-red-700 disabled:bg-gray-400 text-white font-medium rounded-lg transition-colors"
              >
                断开连接
              </button>
              
              <button
                @click="readGenericAccessInfo"
                :disabled="!bluetoothState.isConnected"
                class="w-full px-4 py-2 bg-orange-600 hover:bg-orange-700 disabled:bg-gray-400 text-white font-medium rounded-lg transition-colors"
              >
                读取通用访问信息
              </button>
              
              <button
                @click="findWritableCharacteristics"
                :disabled="!bluetoothState.isConnected"
                class="w-full px-4 py-2 bg-yellow-600 hover:bg-yellow-700 disabled:bg-gray-400 text-white font-medium rounded-lg transition-colors"
              >
                查找可写特征值
              </button>
              
              <button
                @click="tryGenericCommunication"
                :disabled="!bluetoothState.isConnected"
                class="w-full px-4 py-2 bg-purple-600 hover:bg-purple-700 disabled:bg-gray-400 text-white font-medium rounded-lg transition-colors"
              >
                通用设备通信
              </button>
            </div>
          </div>

          <!-- 设备信息 -->
          <div class="bg-white dark:bg-gray-800 rounded-lg p-6 shadow-sm">
            <h2 class="text-xl font-semibold text-gray-900 dark:text-white mb-4">
              设备信息
            </h2>
            <div class="space-y-3">
              <div class="flex justify-between">
                <span class="text-gray-600 dark:text-gray-300">设备名称:</span>
                <span class="text-gray-900 dark:text-white">{{ deviceInfo.name || '未连接' }}</span>
              </div>
              <div class="flex justify-between">
                <span class="text-gray-600 dark:text-gray-300">设备ID:</span>
                <span class="text-gray-900 dark:text-white text-sm">{{ deviceInfo.id || '未连接' }}</span>
              </div>
              <div class="flex justify-between">
                <span class="text-gray-600 dark:text-gray-300">连接状态:</span>
                <span 
                  class="font-medium"
                  :class="deviceInfo.connected ? 'text-green-600' : 'text-red-600'"
                >
                  {{ deviceInfo.connected ? '已连接' : '未连接' }}
                </span>
              </div>
              <div class="flex justify-between">
                <span class="text-gray-600 dark:text-gray-300">电池电量:</span>
                <span class="text-gray-900 dark:text-white">{{ deviceInfo.batteryLevel }}%</span>
              </div>
              <div class="flex justify-between">
                <span class="text-gray-600 dark:text-gray-300">固件版本:</span>
                <span class="text-gray-900 dark:text-white">{{ deviceInfo.firmwareVersion || '未知' }}</span>
              </div>
              <div class="flex justify-between">
                <span class="text-gray-600 dark:text-gray-300">服务数量:</span>
                <span class="text-gray-900 dark:text-white">{{ deviceInfo.services.length }}</span>
              </div>
            </div>
          </div>

          <!-- 设备控制 -->
          <div class="bg-white dark:bg-gray-800 rounded-lg p-6 shadow-sm">
            <h2 class="text-xl font-semibold text-gray-900 dark:text-white mb-4">
              设备控制
            </h2>
            <div class="space-y-4">
              <!-- LED控制 -->
              <div class="flex items-center justify-between">
                <span class="text-gray-600 dark:text-gray-300">LED控制</span>
                <button
                  @click="toggleLED"
                  :disabled="!bluetoothState.isConnected"
                  class="px-4 py-2 rounded-lg font-medium transition-colors"
                  :class="controlCommands.ledOn 
                    ? 'bg-yellow-500 hover:bg-yellow-600 text-white' 
                    : 'bg-gray-300 hover:bg-gray-400 text-gray-700'"
                >
                  {{ controlCommands.ledOn ? '关闭' : '开启' }}
                </button>
              </div>

              <!-- 电机速度控制 -->
              <div>
                <label class="block text-gray-600 dark:text-gray-300 mb-2">
                  电机速度: {{ controlCommands.motorSpeed }}%
                </label>
                <input
                  type="range"
                  min="0"
                  max="100"
                  v-model="controlCommands.motorSpeed"
                  @input="setMotorSpeed(controlCommands.motorSpeed)"
                  :disabled="!bluetoothState.isConnected"
                  class="w-full h-2 bg-gray-200 rounded-lg appearance-none cursor-pointer"
                />
              </div>

              <!-- 温度控制 -->
              <div>
                <label class="block text-gray-600 dark:text-gray-300 mb-2">
                  温度设置: {{ controlCommands.temperature }}°C
                </label>
                <input
                  type="range"
                  min="0"
                  max="50"
                  v-model="controlCommands.temperature"
                  @input="setTemperature(controlCommands.temperature)"
                  :disabled="!bluetoothState.isConnected"
                  class="w-full h-2 bg-gray-200 rounded-lg appearance-none cursor-pointer"
                />
              </div>

              <!-- 湿度控制 -->
              <div>
                <label class="block text-gray-600 dark:text-gray-300 mb-2">
                  湿度设置: {{ controlCommands.humidity }}%
                </label>
                <input
                  type="range"
                  min="0"
                  max="100"
                  v-model="controlCommands.humidity"
                  @input="setHumidity(controlCommands.humidity)"
                  :disabled="!bluetoothState.isConnected"
                  class="w-full h-2 bg-gray-200 rounded-lg appearance-none cursor-pointer"
                />
              </div>
            </div>
          </div>

          <!-- WiFi配置 -->
          <div class="bg-white dark:bg-gray-800 rounded-lg p-6 shadow-sm">
            <h2 class="text-xl font-semibold text-gray-900 dark:text-white mb-4">
              WiFi配置
            </h2>
            <div class="space-y-4">
              <div>
                <label class="block text-gray-600 dark:text-gray-300 mb-2">WiFi名称</label>
                <input
                  type="text"
                  v-model="controlCommands.wifiSsid"
                  placeholder="请输入WiFi名称"
                  :disabled="!bluetoothState.isConnected"
                  class="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-700 text-gray-900 dark:text-white"
                />
              </div>
              <div>
                <label class="block text-gray-600 dark:text-gray-300 mb-2">WiFi密码</label>
                <input
                  type="password"
                  v-model="controlCommands.wifiPassword"
                  placeholder="请输入WiFi密码"
                  :disabled="!bluetoothState.isConnected"
                  class="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-700 text-gray-900 dark:text-white"
                />
              </div>
              <button
                @click="sendWiFiConfig"
                :disabled="!bluetoothState.isConnected"
                class="w-full px-4 py-2 bg-blue-600 hover:bg-blue-700 disabled:bg-gray-400 text-white font-medium rounded-lg transition-colors"
              >
                发送WiFi配置
              </button>
            </div>
          </div>

          <!-- 自定义数据 -->
          <div class="bg-white dark:bg-gray-800 rounded-lg p-6 shadow-sm">
            <h2 class="text-xl font-semibold text-gray-900 dark:text-white mb-4">
              自定义数据
            </h2>
            <div class="space-y-4">
              <div>
                <label class="block text-gray-600 dark:text-gray-300 mb-2">自定义命令</label>
                <input
                  type="text"
                  v-model="controlCommands.customData"
                  placeholder="请输入自定义命令"
                  :disabled="!bluetoothState.isConnected"
                  class="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-700 text-gray-900 dark:text-white"
                />
              </div>
              <button
                @click="sendCustomCommand"
                :disabled="!bluetoothState.isConnected"
                class="w-full px-4 py-2 bg-purple-600 hover:bg-purple-700 disabled:bg-gray-400 text-white font-medium rounded-lg transition-colors"
              >
                发送自定义数据
              </button>
            </div>
          </div>
        </div>

        <!-- 日志面板 -->
        <div class="bg-white dark:bg-gray-800 rounded-lg p-6 shadow-sm">
          <div class="flex items-center justify-between mb-4">
            <h2 class="text-xl font-semibold text-gray-900 dark:text-white">
              操作日志
            </h2>
            <button
              @click="clearLogs"
              class="px-3 py-1 text-sm bg-gray-200 hover:bg-gray-300 dark:bg-gray-700 dark:hover:bg-gray-600 text-gray-700 dark:text-gray-300 rounded transition-colors"
            >
              清除
            </button>
          </div>
          <div class="bg-gray-50 dark:bg-gray-900 rounded-lg p-4 h-96 overflow-y-auto">
            <div class="space-y-1">
              <div
                v-for="(log, index) in logs"
                :key="index"
                class="text-sm text-gray-700 dark:text-gray-300 font-mono"
              >
                {{ log }}
              </div>
              <div v-if="logs.length === 0" class="text-gray-500 dark:text-gray-400 text-center py-8">
                暂无日志信息
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<style scoped>
/* 自定义滚动条 */
.overflow-y-auto::-webkit-scrollbar {
  width: 6px;
}

.overflow-y-auto::-webkit-scrollbar-track {
  background: #f1f1f1;
  border-radius: 3px;
}

.overflow-y-auto::-webkit-scrollbar-thumb {
  background: #c1c1c1;
  border-radius: 3px;
}

.overflow-y-auto::-webkit-scrollbar-thumb:hover {
  background: #a8a8a8;
}

.dark .overflow-y-auto::-webkit-scrollbar-track {
  background: #374151;
}

.dark .overflow-y-auto::-webkit-scrollbar-thumb {
  background: #6b7280;
}

.dark .overflow-y-auto::-webkit-scrollbar-thumb:hover {
  background: #9ca3af;
}

/* 滑块样式 */
input[type="range"] {
  -webkit-appearance: none;
  appearance: none;
  background: transparent;
  cursor: pointer;
}

input[type="range"]::-webkit-slider-track {
  background: #d1d5db;
  height: 8px;
  border-radius: 4px;
}

input[type="range"]::-webkit-slider-thumb {
  -webkit-appearance: none;
  appearance: none;
  background: #3b82f6;
  height: 20px;
  width: 20px;
  border-radius: 50%;
  cursor: pointer;
}

input[type="range"]::-moz-range-track {
  background: #d1d5db;
  height: 8px;
  border-radius: 4px;
  border: none;
}

input[type="range"]::-moz-range-thumb {
  background: #3b82f6;
  height: 20px;
  width: 20px;
  border-radius: 50%;
  cursor: pointer;
  border: none;
}
</style>