<template>
  <view class="page">
    <view class="header-hero">
      <view class="top-bar">
        <view class="top-left" @click="goBack">
          <AppIcon name="chevronLeft" size="sm" color="white" />
        </view>
        <view class="top-center">
          <text class="page-title">{{ t('printers.title') }}</text>
        </view>
        <view class="top-right" @click="isMenuOpen = true">
          <AppIcon name="menu" size="sm" color="white" />
        </view>
      </view>
    </view>

    <view class="content">
      <!-- Current Status -->
      <view class="info-badge">
        <text class="badge-num">{{ currentType ? 1 : 0 }}</text>
        <text class="badge-text">{{ t('printers.connected') }}</text>
      </view>

      <!-- Connected Device -->
      <view v-if="currentType" class="printer-card connected">
        <view class="printer-icon"><AppIcon name="printer" size="md" color="white" /></view>
        <view class="printer-info">
          <text class="printer-name">{{ currentDisplayName }}</text>
          <text class="printer-loc">{{ currentType === 'builtin' ? '127.0.0.1' : (currentBt?.deviceId || '') }}</text>
          <text class="printer-status">{{ t('printers.connected') }}</text>
        </view>
        <view class="printer-actions">
          <button class="btn-test" @click="doTestPrint">{{ t('printers.testPrint') }}</button>
          <button class="btn-disconnect" @click="disconnect">{{ t('printers.disconnect') }}</button>
        </view>
      </view>

      <!-- Built-in Printer (Show when not connected) -->
      <view v-if="!currentType && isBuiltinModeAvailable" class="printer-card" @click="connectBuiltin">
        <view class="printer-icon"><AppIcon name="printer" size="md" color="blue" /></view>
        <view class="printer-info">
          <text class="printer-name">{{ t('printers.builtin') }}</text>
          <text class="printer-loc">{{ t('printers.builtinDesc') }}</text>
        </view>
        <button class="btn-connect">{{ t('printers.connect') }}</button>
      </view>

      <!-- Paired Devices -->
      <template v-if="isBluetoothModeAvailable">
      <!-- #ifdef APP-PLUS -->
      <view class="section-header">
        <text class="section-title">{{ t('printers.pairedDevices') }}</text>
      </view>

      <view v-for="d in pairedDevices" :key="'paired-' + d.deviceId" class="printer-card device-item" @click="connectBt(d)">
        <view class="printer-icon"><AppIcon name="bluetooth" size="md" color="blue" /></view>
        <view class="printer-info">
          <text class="printer-name">{{ d.name || 'Unknown Device' }}</text>
          <text class="printer-loc">{{ d.deviceId }}</text>
        </view>
        <view class="device-meta">
          <text class="device-type-tag" :class="'tag-' + (d.type || 'ble')">{{ getTypeLabel(d.type) }}</text>
          <button class="btn-connect" :disabled="isConnecting">{{ t('printers.connect') }}</button>
        </view>
      </view>

      <view v-if="pairedDevices.length === 0" class="empty-state">
        <text class="empty-text">{{ t('printers.noPairedDevices') }}</text>
      </view>
      <!-- #endif -->

      <!-- Bluetooth Scanning Area -->
      <view class="section-header">
        <text class="section-title">{{ t('printers.nearby') }}</text>
        <view class="header-right">
          <text v-if="isScanning" class="scanning-text">{{ t('printers.scanning') }}</text>
          <button class="btn-scan" @click="isScanning ? stopScan() : startScan()">
            {{ isScanning ? t('printers.stopScan') : t('printers.startScan') }}
          </button>
        </view>
      </view>

      <view v-for="d in devices" :key="d.deviceId" class="printer-card device-item" @click="connectBt(d)">
        <view class="printer-icon"><AppIcon name="bluetooth" size="md" color="blue" /></view>
        <view class="printer-info">
          <text class="printer-name">{{ d.name || 'Unknown Device' }}</text>
          <text class="printer-loc">{{ d.deviceId }}</text>
        </view>
        <view class="device-meta">
          <text v-if="d.type && d.type !== 'unknown'" class="device-type-tag" :class="'tag-' + d.type">{{ getTypeLabel(d.type) }}</text>
          <button class="btn-connect" :disabled="isConnecting">{{ t('printers.connect') }}</button>
        </view>
      </view>

      <view v-if="devices.length === 0 && !isScanning" class="empty-state">
        <text class="empty-text">{{ t('printers.noDevices') }}</text>
      </view>
      </template>

      <view class="collapse-section collapse-section--tips">
        <view class="collapse-header collapse-header--tips" @click="troubleshootingExpanded = !troubleshootingExpanded">
          <text class="collapse-title">Troubleshooting</text>
          <view class="collapse-action-wrap">
            <text class="collapse-action">{{ troubleshootingExpanded ? 'Collapse' : 'Expand' }}</text>
          </view>
        </view>
        <view v-if="troubleshootingExpanded" class="collapse-body">
          <view class="tips-card">
            <text class="tips-item">1. Ensure the printer is powered on and in pairing mode</text>
            <text class="tips-item">2. On Android: enable Location (required for Bluetooth scan)</text>
            <text class="tips-item">3. Place the printer within 10 m and tap Scan again</text>
            <text class="tips-item">4. Devices with no name show as "Unknown Device"—you can still connect</text>
            <text class="tips-item">5. GP-D320FX (d320fx_xxxx): use Bluetooth mode, tap Scan—shows paired + nearby devices, no filtering</text>
            <text class="tips-item">6. Restart the printer or app if not visible</text>
            <text class="tips-item tips-item-last">7. Built-in TSC: defaults to TSPL label commands via UPOS; use Advanced → ESC/POS only if your device is receipt-only.</text>
          </view>
        </view>
      </view>

      <view class="collapse-section collapse-section--debug">
        <view class="collapse-header collapse-header--debug" @click="debugExpanded = !debugExpanded">
          <text class="collapse-title">Debug Status</text>
          <view class="collapse-action-wrap">
            <text class="collapse-action">{{ debugExpanded ? 'Collapse' : 'Expand' }}</text>
          </view>
        </view>
        <view v-if="debugExpanded" class="collapse-body">
          <view class="debug-card">
            <text class="debug-item">Current Mode: {{ debugInfo.currentMode }}</text>
            <text class="debug-item">Available Mode: {{ availablePrinterTypesLabel }}</text>
            <text class="debug-item">Device Model: {{ deviceIdentity.model || '-' }}</text>
            <text class="debug-item">Device Brand: {{ deviceIdentity.brand || '-' }}</text>
            <text class="debug-item">Device Product: {{ deviceIdentity.product || '-' }}</text>
            <text class="debug-item">Classic Module: {{ debugInfo.classicModuleReady ? 'Ready' : 'Not Ready' }}</text>
            <text class="debug-item">Paired Count: {{ debugInfo.pairedCount }}</text>
            <text class="debug-item">Virtual BT Printer: {{ debugInfo.foundVirtualPrinter ? 'Found' : 'Not Found' }}</text>
            <text class="debug-item">Classic Scan: {{ debugInfo.lastClassicEvent }}</text>
            <text class="debug-item">BLE Scan: {{ debugInfo.lastBleEvent }}</text>
            <text v-if="debugInfo.lastBleError" class="debug-item debug-error">{{ debugInfo.lastBleError }}</text>
            <text v-if="debugInfo.locationServiceRequired" class="debug-item debug-warn">
              Android system Location service is OFF. Turn it on in device settings before BLE scan.
            </text>
          </view>
        </view>
      </view>
    </view>

    <canvas
      canvas-id="test-print-canvas-printers"
      id="test-print-canvas-printers"
      :style="{
        position: 'fixed',
        left: '-9999px',
        top: '-9999px',
        width: testCanvasWidth + 'px',
        height: testCanvasHeight + 'px',
        opacity: 0,
        pointerEvents: 'none',
      }"
      :width="testCanvasWidth"
      :height="testCanvasHeight"
    />

    <SideMenu v-model="isMenuOpen" />
  </view>
</template>

<script setup lang="ts">
import { ref, onMounted, onUnmounted, getCurrentInstance, nextTick } from 'vue'
import { useI18n } from 'vue-i18n'
import AppIcon from '../../components/AppIcon.vue'
import SideMenu from '../../components/SideMenu.vue'
import { getDeviceIdentity } from '../../utils/deviceInfo'
import classicBluetooth from '../../utils/print/bluetoothTool.js'
import { ensureBluetoothPermissions } from '../../utils/print/bluetoothPermissions'
import { getAvailablePrinterTypes } from '../../utils/print/printerConnection'
import {
  connectBluetoothPrinter,
  describeDiscoveredPrinter,
  disconnectCurrentPrinter,
  getCurrentPrinterDriver,
  getCurrentPrinterSummary,
  printImageDataForCurrentPrinter,
  useBuiltinPrinter,
} from '../../utils/print/manager/printerManager'
import { getTestPrintCanvasSize, renderTestPrintCanvasImageData } from '../../utils/print/testPrintCanvas'

const { t } = useI18n()
const isMenuOpen = ref(false)
const debugExpanded = ref(false)
const troubleshootingExpanded = ref(false)
const availablePrinterTypes = getAvailablePrinterTypes()
const availablePrinterTypesLabel = availablePrinterTypes.map(item => item === 'builtin' ? 'Built-in' : 'Bluetooth').join(' / ')
const deviceIdentity = getDeviceIdentity()
const isBluetoothModeAvailable = availablePrinterTypes.includes('bluetooth')
const isBuiltinModeAvailable = availablePrinterTypes.includes('builtin')

const currentType = ref<'' | 'bluetooth' | 'builtin'>('')
const currentBt = ref<any>(null)
const currentDisplayName = ref('')
const isScanning = ref(false)
const devices = ref<any[]>([])
const pairedDevices = ref<any[]>([])
const isConnecting = ref(false)
const debugInfo = ref({
  currentMode: 'none',
  classicModuleReady: false,
  pairedCount: 0,
  foundVirtualPrinter: false,
  lastClassicEvent: 'idle',
  lastBleEvent: 'idle',
  lastBleError: '',
  locationServiceRequired: false,
})
const testCanvasWidth = ref(384)
const testCanvasHeight = ref(240)
const pageInstance = getCurrentInstance()?.proxy
let bleListenerRegistered = false

const refreshStatus = () => {
  const summary = getCurrentPrinterSummary()
  currentType.value = summary.type
  currentDisplayName.value = summary.displayName || ''
  debugInfo.value.currentMode = summary.type || 'none'
  currentBt.value = summary.type === 'bluetooth'
    ? {
        deviceName: summary.displayName,
        deviceId: summary.deviceId,
        deviceType: summary.deviceType,
        driverName: summary.driverName,
        protocol: summary.protocol,
      }
    : null
}

function buildClassicDebugSnapshot (): string {
  const summary = getCurrentPrinterSummary()
  const debugState = typeof classicBluetooth?.getDebugState === 'function'
    ? classicBluetooth.getDebugState()
    : null
  const lines: string[] = [
    `driver=${summary.driverKey || '-'}/${summary.driverName || '-'}`,
    `protocol=${summary.protocol || '-'}`,
    `deviceType=${summary.deviceType || '-'}`,
  ]
  if (debugState) {
    lines.push(`classicState=${debugState.connectionState || '-'}`)
    lines.push(`connected=${String(!!debugState.socketConnected)}`)
    lines.push(`outputReady=${String(!!debugState.outputReady)}`)
    lines.push(`sendMode=${debugState.lastSendMode || '-'}`)
    if (debugState.lastSendError || debugState.lastError) {
      lines.push(`lastError=${debugState.lastSendError || debugState.lastError}`)
    }
  }
  return lines.join('\n')
}

const getTypeLabel = (type?: string) => {
  switch (type) {
    case 'classic': return t('printers.classic')
    case 'ble': return t('printers.ble')
    case 'dual': return t('printers.dual')
    default: return t('printers.ble')
  }
}

const normalizeDeviceName = (device: any) => {
  return (device?.localName || device?.name || '').trim() || 'Unknown Device'
}

const hasPreferredClassicDevice = () => {
  return pairedDevices.value.some((item: any) => {
    const name = String(item?.name || '').toLowerCase()
    const driverKey = String(item?.driverKey || '').toLowerCase()
    return name.includes('virtual bt printer') || driverKey === 'd320fax'
  })
}

const addDeviceDedup = (device: any) => {
  const described = describeDiscoveredPrinter(device)
  const existing = devices.value.find(d => d.deviceId === device.deviceId)
  if (!existing) {
    devices.value.push(described)
    return
  }
  Object.assign(existing, described)
}

// #ifdef APP-PLUS
const loadPairedDevices = () => {
  try {
    const list = classicBluetooth.getPairedDevices()
    debugInfo.value.pairedCount = (list || []).length
    debugInfo.value.foundVirtualPrinter = (list || []).some((item: any) => String(item?.name || '').toLowerCase().includes('virtual bt printer'))
    pairedDevices.value = (list || []).map((item: any) => ({
      ...describeDiscoveredPrinter(item),
      name: normalizeDeviceName(item),
    }))
    debugInfo.value.lastClassicEvent = pairedDevices.value.length > 0 ? 'paired devices loaded' : 'no paired devices'
  } catch (e) {
    console.error('Failed to load paired devices', e)
    pairedDevices.value = []
    debugInfo.value.pairedCount = 0
    debugInfo.value.foundVirtualPrinter = false
    debugInfo.value.lastClassicEvent = 'load paired devices failed'
  }
}
// #endif

function mergeCachedBleDevices () {
  uni.getBluetoothDevices({
    success: (res: any) => {
      const list = res.devices || []
      list.forEach((device: any) => {
        addDeviceDedup({
          ...device,
          name: normalizeDeviceName(device),
          type: device.type || 'ble',
        })
      })
    },
  })
}

const startScan = async () => {
  if (isScanning.value) return

  devices.value = []
  debugInfo.value.lastBleError = ''
  debugInfo.value.locationServiceRequired = false
  debugInfo.value.lastClassicEvent = 'starting'
  debugInfo.value.lastBleEvent = 'starting'

  const permissionResult = await ensureBluetoothPermissions({ scan: true, connect: true })
  if (!permissionResult.ok) {
    uni.showToast({ title: permissionResult.message || t('printers.bleNotAvailable'), icon: 'none' })
    return
  }

  uni.openBluetoothAdapter({
    success: () => {
      // #ifdef APP-PLUS
      loadPairedDevices()
      try {
        classicBluetooth.startClassicDiscovery(
          (device: any) => {
            debugInfo.value.lastClassicEvent = 'device found'
            addDeviceDedup({
              ...device,
              name: normalizeDeviceName(device),
            })
          },
          () => {
            debugInfo.value.lastClassicEvent = 'scan finished'
          }
        )
        debugInfo.value.lastClassicEvent = 'scan running'
      } catch (e) {
        console.error('Classic discovery failed', e)
        debugInfo.value.lastClassicEvent = 'scan failed'
      }
      // #endif
      isScanning.value = true

      if (hasPreferredClassicDevice()) {
        debugInfo.value.lastBleEvent = 'skipped (paired classic device found)'
        return
      }

      mergeCachedBleDevices()
      if (!bleListenerRegistered) {
        bleListenerRegistered = true
        uni.onBluetoothDeviceFound((res) => {
          res.devices.forEach(device => {
            addDeviceDedup({
              ...device,
              name: normalizeDeviceName(device),
              type: 'ble',
            })
          })
        })
      }
      uni.startBluetoothDevicesDiscovery({
        allowDuplicatesKey: false,
        success: () => {
          debugInfo.value.lastBleEvent = 'scan running'
        },
        fail: (err) => {
          console.error('BLE startBluetoothDevicesDiscovery fail:', err)
          debugInfo.value.lastBleEvent = 'scan failed'
          debugInfo.value.lastBleError = err?.errMsg || 'BLE scan failed'
          if (err?.errCode === 10016 || err?.code === 10016) {
            debugInfo.value.locationServiceRequired = true
            debugInfo.value.lastBleError = 'BLE scan failed: system Location service is turned off.'
            uni.showToast({
              title: 'Turn on system Location service first',
              icon: 'none',
              duration: 2500,
            })
          }
        }
      })
    },
    fail: (err) => {
      console.error('openBluetoothAdapter fail:', err)
      if (devices.value.length === 0 && pairedDevices.value.length === 0) {
        uni.showToast({ title: t('printers.bleNotAvailable'), icon: 'none' })
      }
    }
  })
}

const stopScan = () => {
  isScanning.value = false
  debugInfo.value.lastClassicEvent = 'stopped'
  debugInfo.value.lastBleEvent = 'stopped'
  uni.stopBluetoothDevicesDiscovery({
    success: () => console.log('Stop BLE scan success'),
    fail: (err) => console.error('Stop BLE scan fail', err)
  })
  // #ifdef APP-PLUS
  try {
    classicBluetooth.cancelClassicDiscovery()
  } catch (e) {
    console.error('Cancel classic discovery failed', e)
  }
  // #endif
}

const connectBt = async (device: any) => {
  if (isConnecting.value) return
  isConnecting.value = true
  stopScan()

  const permissionResult = await ensureBluetoothPermissions({ connect: true })
  if (!permissionResult.ok) {
    isConnecting.value = false
    uni.showToast({ title: permissionResult.message || t('printers.connectFail'), icon: 'none' })
    return
  }

  uni.showLoading({ title: t('printers.connecting') })
  try {
    await connectBluetoothPrinter(device)
    refreshStatus()
    uni.hideLoading()
    uni.showToast({ title: t('printers.connectSuccess') })
  } catch (e) {
    uni.hideLoading()
    uni.showToast({ title: t('printers.connectFail'), icon: 'none' })
  } finally {
    isConnecting.value = false
  }
}

const connectBuiltin = () => {
  useBuiltinPrinter()
  refreshStatus()
  uni.showToast({ title: t('printers.connectSuccess') })
}

const disconnect = async () => {
  await disconnectCurrentPrinter()
  refreshStatus()
  uni.showToast({ title: t('printers.disconnected') })
}

/** 测试打印：仅下发位图，不调用 `/api/app/us-app-labeling/print`（接口 9 仅预览页出纸后落库） */
const doTestPrint = async () => {
  try {
    uni.showLoading({ title: 'Rendering canvas...', mask: true })
    const driver = getCurrentPrinterDriver()
    const size = getTestPrintCanvasSize(driver.imageMaxWidthDots || (driver.protocol === 'esc' ? 384 : 800))
    testCanvasWidth.value = size.width
    testCanvasHeight.value = size.height
    await nextTick()
    const imageData = await renderTestPrintCanvasImageData('test-print-canvas-printers', pageInstance, size)
    await printImageDataForCurrentPrinter(imageData, { printQty: 1 }, (percent) => {
      if (percent < 100) {
        uni.showLoading({ title: `Printing ${percent}%`, mask: true })
      }
    })
    uni.hideLoading()
    uni.showToast({ title: t('printers.testPrintSuccess') })
  } catch (e: any) {
    uni.hideLoading()
    const msg = (e && e.message) ? e.message : 'Print failed'
    if (msg.indexOf('Built-in printer') !== -1 || msg === 'BUILTIN_PLUGIN_NOT_FOUND') {
      uni.showModal({
        title: 'Print Failed',
        content: 'Built-in TCP printing is not available on this device. Please switch to Bluetooth mode and scan for your printer. Check Android Bluetooth settings to pair with "Virtual BT Printer" or your printer model first.',
        confirmText: 'OK',
        showCancel: false,
      })
    } else {
      /** 默认系统弹框：不设置大小，直接把调试日志写入 content，便于拍照/复制 */
      const debugText = buildClassicDebugSnapshot()
      uni.showModal({
        title: 'Print Failed',
        content: `${msg}\n\n${debugText}`.trim(),
        confirmText: 'OK',
        showCancel: false,
      })
    }
  }
}

const goBack = () => {
  const pages = getCurrentPages()
  if (pages.length > 1) {
    uni.navigateBack()
  } else {
    uni.redirectTo({ url: '/pages/index/index' })
  }
}

onMounted(() => {
  refreshStatus()
  debugInfo.value.classicModuleReady = !!classicBluetooth
  // #ifdef APP-PLUS
  loadPairedDevices()
  // #endif
})

onUnmounted(() => {
  if (isScanning.value) stopScan()
  if (bleListenerRegistered) {
    bleListenerRegistered = false
    try {
      if (typeof uni.offBluetoothDeviceFound === 'function') {
        uni.offBluetoothDeviceFound()
      }
    } catch (_) {}
  }
  // 不在离开设置页时 closeBluetoothAdapter：否则标签预览等页面打印会 writeBLECharacteristicValue:fail not init（与 Test Print 同页才正常）。
  // 需要释放蓝牙时请用户点「断开」或系统层关闭蓝牙。
})
</script>

<style scoped>
.page { min-height: 100vh; background: #f9fafb; }

.header-hero {
  background: linear-gradient(135deg, var(--theme-primary), var(--theme-primary-dark));
  padding: 48rpx 32rpx 24rpx;
}
.top-bar { height: 96rpx; display: flex; align-items: center; justify-content: space-between; }
.top-left, .top-right { width: 64rpx; height: 64rpx; border-radius: 999rpx; background: rgba(255,255,255,0.15); display: flex; align-items: center; justify-content: center; }
.top-center { flex: 1; text-align: center; }
.page-title { font-size: 34rpx; font-weight: 600; color: #fff; }

.content {
  padding: 48rpx;
  padding-bottom: calc(48rpx + env(safe-area-inset-bottom));
}
.collapse-section {
  width: 100%;
  margin-top: 32rpx;
  border-radius: 16rpx;
  overflow: hidden;
  box-sizing: border-box;
  box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.04);
}
.collapse-section--tips,
.collapse-section--debug {
  border: 1rpx solid rgba(31, 58, 138, 0.22);
  background: var(--theme-primary-light, #e8ecf5);
}
.collapse-header {
  width: 100%;
  display: flex;
  flex-direction: row;
  flex-wrap: nowrap;
  align-items: center;
  justify-content: space-between;
  padding: 28rpx 32rpx;
  box-sizing: border-box;
}
.collapse-header--tips,
.collapse-header--debug {
  background: #d6dff0;
}
.collapse-title {
  flex: 1;
  min-width: 0;
  font-size: 30rpx;
  font-weight: 600;
  color: var(--theme-primary, #1f3a8a);
  text-align: left;
}
.collapse-action-wrap {
  flex-shrink: 0;
  margin-left: 24rpx;
  display: flex;
  align-items: center;
  justify-content: flex-end;
}
.collapse-action {
  font-size: 28rpx;
  font-weight: 500;
  color: var(--theme-primary);
  white-space: nowrap;
  text-align: right;
}
.collapse-body {
  border-top: 1rpx solid rgba(31, 58, 138, 0.12);
}
.tips-card {
  background: var(--theme-primary-light, #e8ecf5);
  border: none;
  border-radius: 0;
  padding: 24rpx 32rpx;
  display: flex;
  flex-direction: column;
  gap: 8rpx;
}
.tips-item {
  font-size: 24rpx;
  color: #334155;
  line-height: 1.5;
}
.tips-item-last {
  margin-bottom: 0;
}
.info-badge { display: flex; align-items: center; gap: 12rpx; margin-bottom: 32rpx; }
.badge-num { font-size: 40rpx; font-weight: 700; color: var(--theme-primary); }
.badge-text { font-size: 28rpx; color: #6b7280; }
.debug-card {
  background: var(--theme-primary-light, #e8ecf5);
  border: none;
  border-radius: 0;
  padding: 24rpx 32rpx;
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: 8rpx;
}
.debug-item { font-size: 22rpx; color: #334155; }
.debug-error { color: #b91c1c; }
.debug-warn { color: #92400e; font-weight: 600; }
.printer-card { background: #fff; padding: 32rpx; border-radius: 24rpx; margin-bottom: 24rpx; display: flex; align-items: center; gap: 24rpx; box-shadow: 0 4rpx 12rpx rgba(0,0,0,0.05); border: 1rpx solid #f3f4f6; }
.printer-card.connected { background: var(--theme-primary); border: none; }
.printer-card.connected .printer-name, .printer-card.connected .printer-loc, .printer-card.connected .printer-status { color: #fff; }
.printer-card.connected .printer-icon { background: rgba(255,255,255,0.2); }

.printer-icon { width: 88rpx; height: 88rpx; background: #eff6ff; border-radius: 16rpx; display: flex; align-items: center; justify-content: center; flex-shrink: 0; }
.printer-info { flex: 1; display: flex; flex-direction: column; gap: 4rpx; }
.printer-name { font-size: 32rpx; font-weight: 600; color: #111827; }
.printer-loc { font-size: 24rpx; color: #6b7280; }
.printer-status { font-size: 24rpx; font-weight: 500; color: var(--theme-primary); }

.printer-actions { display: flex; flex-direction: column; gap: 12rpx; }
.btn-test, .btn-disconnect, .btn-connect, .btn-scan { 
  margin: 0; padding: 0 24rpx; height: 60rpx; line-height: 60rpx; font-size: 24rpx; border-radius: 12rpx; border: none;
}
.btn-test { background: #fff; color: var(--theme-primary); }
.btn-disconnect { background: rgba(255,255,255,0.2); color: #fff; }
.btn-connect { background: var(--theme-primary); color: #fff; }
.btn-connect[disabled] { opacity: 0.6; }

.section-header { display: flex; align-items: center; justify-content: space-between; margin: 48rpx 0 24rpx; }
.section-title { font-size: 30rpx; font-weight: 700; color: #374151; }
.header-right { display: flex; align-items: center; gap: 16rpx; }
.scanning-text { font-size: 24rpx; color: #9ca3af; }
.btn-scan { background: #f3f4f6; color: #4b5563; }

.empty-state { padding: 80rpx 0; text-align: center; }
.empty-text { font-size: 28rpx; color: #9ca3af; }

.device-meta { display: flex; flex-direction: column; align-items: flex-end; gap: 12rpx; flex-shrink: 0; }
.device-type-tag { display: inline-block; padding: 4rpx 16rpx; font-size: 20rpx; border-radius: 8rpx; font-weight: 500; }
.tag-ble { background: #eff6ff; color: #3b82f6; }
.tag-classic { background: #fef3c7; color: #d97706; }
.tag-dual { background: #ecfdf5; color: #059669; }
</style>
