<template>
  <div class="scan-page">
    <div class="scan-header">设备点检扫码</div>

    <div class="scan-box">
      <div class="tip">将二维码置于取景框内自动识别，或手动输入设备ID</div>
      <div class="camera-area">
        <video ref="videoRef" playsinline autoplay muted class="camera-video"></video>
        <canvas ref="canvasRef" class="hidden-canvas"></canvas>
        <div class="scan-frame"></div>
      </div>
      <div class="row mt-8px">
        <el-button size="small" @click="toggleCamera" :loading="cameraLoading">{{ cameraOn ? '关闭相机' : '开启相机'
        }}</el-button>
        <el-button size="small" @click="switchFacing" :disabled="!cameraOn">切换前后摄</el-button>
      </div>
      <el-input v-model.trim="manualId" placeholder="请输入设备ID" inputmode="numeric" class="mt-12px" clearable />
      <el-checkbox v-model="batchMode" class="mt-8px">批量执行同分类任务</el-checkbox>
      <el-button type="primary" class="mt-12px w-full" @click="go" :loading="loading">开始点检</el-button>
    </div>

    <div class="footer-actions">
      <el-button text type="primary" @click="openHelp">使用说明</el-button>
      <el-button text type="info" @click="toggleDebug">{{ showDebug ? '隐藏调试' : '显示调试' }}</el-button>
    </div>

    <!-- 调试信息面板 -->
    <div v-if="showDebug" class="debug-panel">
      <div class="debug-title">🔍 调试信息</div>
      <div class="debug-content">
        <div><strong>摄像头状态:</strong> {{ cameraOn ? '已开启' : '未开启' }}</div>
        <div><strong>扫描状态:</strong> {{ scanningStatus }}</div>
        <div><strong>设备ID:</strong> {{ manualId || '未输入' }}</div>
        <div><strong>浏览器支持:</strong></div>
        <div class="debug-indent">- MediaDevices: {{ browserSupport.mediaDevices ? '✅' : '❌' }}</div>
        <div class="debug-indent">- BarcodeDetector: {{ browserSupport.barcodeDetector ? '✅' : '❌' }}</div>
        <div class="debug-indent">- @zxing/browser: {{ zxingLoaded ? '✅' : '❌' }}</div>
        <div><strong>最后扫描内容:</strong> {{ lastScannedContent || '无' }}</div>
        <div><strong>扫描次数:</strong> {{ scanCount }}</div>
      </div>
    </div>
  </div>
</template>

<script lang="ts" setup>
import { ProductApi } from '@/api/iot/product/product'
import { ProductCategoryApi } from '@/api/iot/product/category'
import { InspectionInstanceApi } from '@/api/iot/inspection/instance'

const router = useRouter()
const route = useRoute()
const message = useMessage()
const manualId = ref<string>('')
const loading = ref(false)
const showDebug = ref(false)
const scanningStatus = ref('未开始')
const lastScannedContent = ref('')
const scanCount = ref(0)
const zxingLoaded = ref(false)
const batchMode = ref(false)

// 防重复提交标志
const isProcessing = ref(false)

// 计算属性用于模板中的浏览器支持检测
const browserSupport = computed(() => ({
  mediaDevices: !!globalThis.navigator?.mediaDevices,
  barcodeDetector: !!(globalThis as any).BarcodeDetector
}))

const videoRef = ref<HTMLVideoElement | null>(null)
const canvasRef = ref<HTMLCanvasElement | null>(null)
const cameraOn = ref(false)
const cameraLoading = ref(false)
let mediaStream: MediaStream | null = null
let facingMode: 'environment' | 'user' = 'environment'
let stopScanLoop: (() => void) | null = null

onMounted(() => {
  const did = (route.query.deviceId as string) || ''
  if (did) {
    manualId.value = did
  }
  const batch = (route.query.batch as string) || ''
  batchMode.value = batch === '1'
})

onBeforeUnmount(() => {
  stopCamera()
})

// 通用的设备验证和模板检查函数
const validateDeviceAndTemplate = async (deviceId: string) => {
  // 防重复处理
  if (isProcessing.value) {
    console.log('🚫 正在处理中，跳过重复请求')
    return false
  }

  isProcessing.value = true
  loading.value = true

  try {
    console.log('🔍 开始验证设备，ID:', deviceId)

    // 获取设备（产品）信息
    const product = await ProductApi.getProduct(Number(deviceId))
    console.log('📱 获取到产品信息:', product)
    const categoryName = (product as any)?.categoryName as string

    if (!categoryName) {
      message.warning('设备未设置分类，无法匹配点检模板')
      return false
    }

    // 检查是否有对应的模板
    const categoryId = (product as any)?.categoryId
    if (!categoryId) {
      message.warning('产品未设置分类，无法匹配点检模板')
      return false
    }

    console.log('🏷️ 获取分类信息，ID:', categoryId)
    const category = await ProductCategoryApi.getProductCategory(categoryId)
    console.log('📋 获取到分类信息:', category)

    // 检查是否有模板
    const templateField = category.inspectTemplate || category.inspectionTemplate || category.template
    if (!templateField || templateField.trim() === '') {
      message.warning(`未找到"${categoryName}"分类的点检模板，请联系管理员配置`)
      return false
    }

    // 获取设备当前进行中的任务实例
    let currentInstance: any = null
    try {
      const response = await InspectionInstanceApi.getCurrentByDevice(deviceId)
      console.log('📋 设备任务实例响应:', response)

      // 检查响应结构，API返回的是 { code: 0, data: [...], msg: "" }
      const instances = response.data || response
      console.log('📋 解析后的任务实例数据:', instances)

      if (instances && instances.length > 0) {
        currentInstance = instances[0]
        console.log('🎯 当前任务ID:', currentInstance?.taskId)
        console.log('📝 任务名称:', currentInstance?.taskName)
        console.log('👤 指派用户:', currentInstance?.assigneeUserName)
        console.log('📊 实例状态:', currentInstance?.status)
        console.log('🕐 窗口时间:', currentInstance?.windowStartTime, '~', currentInstance?.windowEndTime)

        // 将实例信息存储到sessionStorage，供CheckExecute页面使用
        sessionStorage.setItem('currentInspectionInstance', JSON.stringify(currentInstance))
      } else {
        console.log('ℹ️ 该设备当前没有进行中的任务实例')
        // 清除之前的实例信息
        sessionStorage.removeItem('currentInspectionInstance')
      }
    } catch (e: any) {
      console.warn('⚠️ 获取任务实例失败:', e?.message || '未知错误')
      // 清除之前的实例信息
      sessionStorage.removeItem('currentInspectionInstance')
    }

    // 跳转到点检执行页面（公开无布局路由）
    router.replace({
      name: 'IoTCheckExecutePublic',
      params: { deviceId },
      query: batchMode.value ? { batch: '1' } : {}
    })
    return true
  } catch (e: any) {
    message.error('获取设备信息失败：' + (e?.message || '设备不存在'))
    return false
  } finally {
    loading.value = false
    isProcessing.value = false
  }
}

const go = async () => {
  if (!manualId.value) {
    message.warning('请输入设备ID')
    return
  }

  await validateDeviceAndTemplate(manualId.value)
}

const openHelp = () => {
  message.info('推荐使用后置摄像头；如相机不可用，请手动输入设备ID。')
}

const toggleDebug = () => {
  showDebug.value = !showDebug.value
}

const toggleCamera = async () => {
  if (cameraOn.value) {
    stopCamera()
  } else {
    await startCamera()
  }
}

const switchFacing = async () => {
  facingMode = facingMode === 'environment' ? 'user' : 'environment'
  if (cameraOn.value) {
    await startCamera(true)
  }
}

async function startCamera(restart = false) {
  if (!videoRef.value) return
  cameraLoading.value = true
  try {
    if (restart) stopCamera()
    mediaStream = await navigator.mediaDevices.getUserMedia({
      video: { facingMode, width: { ideal: 1280 }, height: { ideal: 720 } },
      audio: false
    })
    videoRef.value.srcObject = mediaStream
    await videoRef.value.play()
    cameraOn.value = true
    startScanLoop()
  } catch (e: any) {
    message.error('无法打开摄像头：' + (e?.message || '请检查浏览器权限'))
  } finally {
    cameraLoading.value = false
  }
}

function stopCamera() {
  stopScanLoop && stopScanLoop()
  if (mediaStream) {
    mediaStream.getTracks().forEach(t => t.stop())
  }
  mediaStream = null
  cameraOn.value = false
}

async function parseAndGo(text: string) {
  // 防重复处理
  if (isProcessing.value) {
    console.log('🚫 正在处理中，跳过重复扫码')
    return
  }

  lastScannedContent.value = text
  scanCount.value++

  let deviceId = ''

  // 检查是否为纯数字（产品ID）
  if (/^\d+$/.test(text)) {
    deviceId = text
  } else {
    // 兼容旧的URL格式
    try {
      const url = new URL(text)
      const did = url.searchParams.get('deviceId') || ''
      if (did) {
        deviceId = did
      }
    } catch (e) {
      // URL解析失败，忽略
    }
  }

  if (deviceId) {
    // 立即停止扫描循环，防止重复扫码
    stopCamera()
    await validateDeviceAndTemplate(deviceId)
  } else {
    message.warning('无法识别的二维码内容，请确保二维码包含有效的产品ID')
  }
}

function startScanLoop() {
  scanningStatus.value = '扫描中...'
  let canceled = false
  stopScanLoop = () => {
    scanningStatus.value = '已停止'
    canceled = true
  }

  // @ts-ignore
  const NativeDetector = (window as any).BarcodeDetector

  if (NativeDetector) {
    const detector = new NativeDetector({ formats: ['qr_code'] })
    let lastTick = 0
    const tick = async (ts: number) => {
      if (canceled || !videoRef.value || !canvasRef.value) return
      if (ts - lastTick < 200) {
        requestAnimationFrame(tick)
        return
      }
      lastTick = ts
      try {
        const video = videoRef.value
        const canvas = canvasRef.value
        if (video.videoWidth && video.videoHeight) {
          if (canvas.width !== video.videoWidth || canvas.height !== video.videoHeight) {
            canvas.width = video.videoWidth
            canvas.height = video.videoHeight
          }
          const ctx = canvas.getContext('2d')!
          ctx.drawImage(video, 0, 0, canvas.width, canvas.height)
          const codes = await detector.detect(canvas as any)
          // @ts-ignore
          if (codes && codes.length) {
            const v = (codes[0].rawValue || codes[0].raw || '').toString()
            if (v) {
              parseAndGo(v)
              return
            }
          }
        }
      } catch (e) {
        // 检测器错误，忽略
      }
      requestAnimationFrame(tick)
    }
    requestAnimationFrame(tick)
    return
  }

  // 使用@zxing/browser库
  ; (async () => {
    try {
      const { BrowserQRCodeReader } = await import('@zxing/browser')
      zxingLoaded.value = true
      const reader = new BrowserQRCodeReader()
      const video = videoRef.value!
      const controls = await reader.decodeFromVideoDevice(undefined, video, (result) => {
        const text = result?.getText?.()
        if (text) parseAndGo(text)
      })
      stopScanLoop = () => {
        controls.stop();
        canceled = true
      }
    } catch (e) {
      zxingLoaded.value = false
      message.warning('缺少扫码能力，请手动输入设备ID')
    }
  })()
}
</script>

<style scoped>
.scan-page {
  padding: 16px;
}

.scan-header {
  font-size: 20px;
  font-weight: 600;
  margin-bottom: 12px;
}

.scan-box {
  background: #fff;
  border-radius: 8px;
  padding: 16px;
}

.tip {
  color: #666;
  font-size: 13px;
  margin-bottom: 12px;
}

.camera-area {
  position: relative;
  width: 100%;
  height: 260px;
  background: #000;
  border-radius: 8px;
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
}

.camera-video {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.hidden-canvas {
  display: none;
}

.scan-frame {
  position: absolute;
  width: 70%;
  height: 60%;
  border: 2px solid rgba(255, 255, 255, 0.8);
  border-radius: 8px;
}

.row {
  display: flex;
  gap: 8px;
}

.w-full {
  width: 100%;
}

.mt-12px {
  margin-top: 12px;
}

.mt-8px {
  margin-top: 8px;
}

.debug-panel {
  margin-top: 16px;
  padding: 12px;
  background: #f5f5f5;
  border-radius: 8px;
  border: 1px solid #ddd;
}

.debug-title {
  font-weight: 600;
  margin-bottom: 8px;
  color: #333;
}

.debug-content {
  font-size: 12px;
  line-height: 1.5;
}

.debug-indent {
  margin-left: 16px;
}
</style>
