global.wx = global.wx || {
  onBLEConnectionStateChange: function () {}
}

const ble = require('../services/ble')

function assert(condition, message) {
  if (!condition) throw new Error(message)
}

function bytes(buffer) {
  return Array.from(new Uint8Array(buffer))
}

function xor(arr) {
  return arr.reduce((acc, item) => acc ^ item, 0)
}

function testBuildFrameChecksum() {
  const frame = bytes(ble.buildFrame(0x02, [0x7F, 0x01]))
  assert(frame[0] === 0xAA && frame[1] === 0x55, 'frame header mismatch')
  assert(frame[2] === 0x02, 'frame length mismatch')
  assert(frame[3] === 0x02, 'frame type mismatch')
  assert(frame[frame.length - 1] === xor(frame.slice(0, -1)), 'checksum must include header, len, type, payload')
}

function testParseStatusFrame() {
  const payload = [0x02, 0x7F, 0x02, 200, 0x00, 0x09, 0x27, 0xC0, 0x00, 0x01, 86, 36, 1, 2]
  const frame = ble.buildFrame(0x21, payload)
  const parsed = ble.parseFrame(frame)
  assert(parsed.type === 0x21, 'status type mismatch')
  const status = ble.parseStatusReport(parsed.payload)
  assert(status.mode_state === 0x02, 'mode_state mismatch')
  assert(status.region_mask === 0x7F, 'region mask mismatch')
  assert(status.remaining_ms === 600000, 'remaining_ms mismatch')
  assert(status.battery === 86, 'battery mismatch')
  assert(status.temperature === 36, 'temperature mismatch')
}

function testBindPayloadLength() {
  const userBytes = ble.hexToBytes('0000000000000001')
  const tokenBytes = ble.hexToBytes('0011223344556677')
  assert(userBytes.length === 8, 'user id must be 8 bytes')
  assert(tokenBytes.length === 8, 'bind token must be 8 bytes')
}

function testVendorCommand33() {
  const command = ble.buildVendorCommand33({
    region_mask: 0x1F,
    wavelength: ble.WAVELENGTH.R,
    brightness: 200,
    duration_ms: 600000
  })
  assert(command.length === 33, 'vendor command must be 33 bytes')
  assert(command[32] === xor(command.slice(0, 32)), 'vendor command checksum mismatch')
}

testBuildFrameChecksum()
testParseStatusFrame()
testBindPayloadLength()
testVendorCommand33()

console.log('BLE frame tests passed')
