<template>
	<view class="device-page">
		<view class="search-row">
			<view class="search-box">
				<uni-icons type="search" size="16" color="#7b8794"></uni-icons>
				<input class="search-input" placeholder="搜索设备名称或SN" v-model="searchKeyword" @confirm="fetchMyDevices" />
				<button v-if="searchKeyword" class="clear-btn" @click="clearSearch">×</button>
			</view>
			<button class="scan-chip" @click="refreshScan">扫描连接</button>
		</view>

		<view class="section" v-if="scannedDevices.length">
			<view class="section-head">
				<text class="section-title">可连接设备</text>
				<text class="section-sub">点击连接后自动写入后端</text>
			</view>
			<view v-for="s in scannedDevices" :key="s.deviceId" class="device-card" @click="askConnect(s)">
				<image class="device-icon" :src="getIconForType()" mode="aspectFit" />
				<view class="device-main">
					<text class="device-name">{{ s.name }}</text>
					<text class="device-meta">SN: {{ s.deviceId }}</text>
				</view>
				<view class="state-pill running">连接</view>
			</view>
		</view>

		<scroll-view class="content" scroll-y>
			<view class="section">
				<view class="section-head">
					<text class="section-title">我的设备</text>
					<text class="section-sub">后端持久化数据</text>
				</view>

				<view v-if="deviceList.length === 0" class="empty-card">
					<text>暂无设备，请先扫描连接</text>
				</view>

				<view v-for="item in deviceList" :key="item.deviceId" class="device-card" @click="gotoDetail(item)">
					<image class="device-icon" :src="getIconForType()" mode="aspectFit" />
					<view class="device-main">
						<text class="device-name">{{ item.deviceName || '未命名设备' }}</text>
						<text class="device-meta">SN: {{ item.deviceSn || '--' }}</text>
						<text class="device-meta" v-if="item.lastConnectedAt">最近连接：{{ formatTime(item.lastConnectedAt) }}</text>
					</view>
					<view class="device-actions">
						<view class="state-pill" :class="item.status === '0' ? 'running' : 'offline'">
							{{ item.status === '0' ? '正常' : '停用' }}
						</view>
						<button class="delete-btn" @click.stop="removeDevice(item)">
							<uni-icons type="trash" size="12" color="#64748b"></uni-icons>
							<text>删除</text>
						</button>
					</view>
				</view>
			</view>
		</scroll-view>
	</view>
</template>

<script>
	import { listMyDevices, deleteMyDevices, addMyDevice, updateMyDevice } from '@/api/device'

	export default {
		data() {
			return {
				searchKeyword: '',
				deviceList: [],
				scannedDevices: [],
				_bluetoothFoundHandler: null
			}
		},
		onLoad() {
			this.fetchMyDevices()
		},
		onUnload() {
			this.stopScan()
		},
		methods: {
			fetchMyDevices() {
				const params = {}
				if ((this.searchKeyword || '').trim()) params.deviceName = this.searchKeyword.trim()
				listMyDevices(params).then(res => {
					this.deviceList = Array.isArray(res.rows) ? res.rows : []
				})
			},
			clearSearch() {
				this.searchKeyword = ''
				this.fetchMyDevices()
			},
			refreshScan() {
				this.scannedDevices = []
				this.startScan()
			},
			startScan() {
				uni.openBluetoothAdapter({
					success: () => {
						uni.startBluetoothDevicesDiscovery({
							allowDuplicatesKey: false,
							success: () => {
								if (this._bluetoothFoundHandler) {
									try { uni.offBluetoothDeviceFound(this._bluetoothFoundHandler) } catch (e) {}
								}
								this._bluetoothFoundHandler = res => {
									const arr = res.devices || []
									arr.forEach(dev => {
										const id = dev.deviceId
										const name = (dev.name || dev.localName || '').trim()
										if (!id || !name) return
										if (this.scannedDevices.some(s => s.deviceId === id)) return
										this.scannedDevices.push({ deviceId: id, name })
									})
								}
								uni.onBluetoothDeviceFound(this._bluetoothFoundHandler)
								uni.showToast({ title: '扫描中...', icon: 'none' })
								setTimeout(() => this.stopScan(), 10000)
							}
						})
					},
					fail: () => uni.showToast({ title: '请开启蓝牙权限', icon: 'none' })
				})
			},
			stopScan() {
				try { uni.stopBluetoothDevicesDiscovery({}) } catch (e) {}
				if (this._bluetoothFoundHandler) {
					try { uni.offBluetoothDeviceFound(this._bluetoothFoundHandler) } catch (e) {}
					this._bluetoothFoundHandler = null
				}
			},
			askConnect(device) {
				uni.showModal({
					title: '连接确认',
					content: `连接设备「${device.name}」后将自动写入后端，是否继续？`,
					success: res => {
						if (res.confirm) this.connectDevice(device)
					}
				})
			},
			connectDevice(device) {
				uni.showLoading({ title: '连接中...' })
				uni.createBLEConnection({
					deviceId: device.deviceId,
					success: () => {
						this.upsertDeviceToServer(device).finally(() => uni.hideLoading())
					},
					fail: () => {
						uni.hideLoading()
						uni.showToast({ title: '连接失败', icon: 'none' })
					}
				})
			},
			upsertDeviceToServer(device) {
				const exist = this.deviceList.find(d => d.deviceSn === device.deviceId)
				const payload = {
					deviceName: device.name,
					deviceSn: device.deviceId,
					deviceType: 'attractor',
					status: '0',
					lastConnectedAt: new Date().toISOString()
				}
				if (exist) {
					return updateMyDevice({ ...payload, deviceId: exist.deviceId }).then(() => {
						uni.showToast({ title: '连接成功，已更新', icon: 'success' })
						this.fetchMyDevices()
					})
				}
				return addMyDevice(payload).then(() => {
					uni.showToast({ title: '连接成功，已入库', icon: 'success' })
					this.fetchMyDevices()
				})
			},
			formatTime(ts) {
				if (!ts) return ''
				const d = new Date(ts)
				const y = d.getFullYear()
				const m = String(d.getMonth() + 1).padStart(2, '0')
				const day = String(d.getDate()).padStart(2, '0')
				const h = String(d.getHours()).padStart(2, '0')
				const min = String(d.getMinutes()).padStart(2, '0')
				return `${y}-${m}-${day} ${h}:${min}`
			},
			getIconForType() {
				return '/static/images/app_icon_pack_schemeA_tealLogo/master_1024.png'
			},
			removeDevice(item) {
				uni.showModal({
					title: '删除设备',
					content: '确认删除该设备吗？',
					success: res => {
						if (res.confirm) {
							deleteMyDevices(item.deviceId).then(() => {
								uni.showToast({ title: '删除成功', icon: 'none' })
								this.fetchMyDevices()
							})
						}
					}
				})
			},
			gotoDetail(device) {
				if (!device || !device.deviceSn) return
				uni.navigateTo({ url: `/pages/devices/attractor/attractor?deviceId=${encodeURIComponent(device.deviceSn)}` })
			}
		}
	}
</script>

<style scoped>
	.device-page { min-height: 100vh; background: #f4f7f8; padding: 20rpx 20rpx 0; box-sizing: border-box; }
	.search-row { display: flex; gap: 12rpx; align-items: center; margin-bottom: 18rpx; }
	.search-box { flex: 1; height: 72rpx; display: flex; align-items: center; gap: 10rpx; padding: 0 16rpx; background: #fff; border-radius: 14rpx; border: 1rpx solid #e7eeef; }
	.search-input { flex: 1; font-size: 24rpx; color: #0f172a; }
	.clear-btn { border: none; background: transparent; font-size: 32rpx; color: #9ca3af; line-height: 1; }
	.scan-chip { height: 72rpx; padding: 0 16rpx; border-radius: 14rpx; background: #e6f5f4; border: 1rpx solid #bfe9e7; display: flex; align-items: center; font-size: 22rpx; color: #0f7f7a; }
	.content { height: calc(100vh - 240rpx); }
	.section { margin-bottom: 20rpx; }
	.section-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 12rpx; }
	.section-title { font-size: 26rpx; font-weight: 600; color: #0f172a; }
	.section-sub { font-size: 22rpx; color: #94a3b8; }
	.empty-card { background: #fff; border-radius: 16rpx; border: 1rpx dashed #d6dde3; padding: 24rpx; text-align: center; color: #94a3b8; font-size: 24rpx; }
	.device-card { display: flex; align-items: center; padding: 18rpx; border-radius: 18rpx; background: #fff; border: 1rpx solid #e7eeef; margin-bottom: 12rpx; }
	.device-icon { width: 70rpx; height: 70rpx; border-radius: 16rpx; background: #f2f7f6; margin-right: 16rpx; }
	.device-main { flex: 1; display: flex; flex-direction: column; gap: 4rpx; }
	.device-name { font-size: 26rpx; font-weight: 600; color: #0f172a; }
	.device-meta { font-size: 22rpx; color: #94a3b8; }
	.device-actions { display: flex; flex-direction: column; align-items: flex-end; gap: 10rpx; }
	.state-pill { padding: 4rpx 12rpx; border-radius: 999rpx; font-size: 20rpx; font-weight: 600; background: #f1f5f9; color: #64748b; }
	.state-pill.running { background: #ecfdf3; color: #059669; }
	.state-pill.offline { background: #f1f5f9; color: #94a3b8; }
	.delete-btn { display: inline-flex; align-items: center; gap: 6rpx; height: 44rpx; padding: 0 12rpx; border-radius: 12rpx; border: 1rpx solid #e2e8f0; background: #f8fafc; color: #64748b; font-size: 20rpx; }
</style>
