<template>
  <view class="container">
    <!-- 自定义扫码界面 -->
    <view class="scanner-container" v-if="isScanning">
      <!-- 顶部操作栏 -->
      <view class="scanner-header">
        <view class="back-btn" @click="cancelScan">返回</view>
        <view class="title">扫码</view>
        <view class="empty"></view>
      </view>
      
      <!-- 相机预览区域 -->
      <view class="camera-preview">
        <!-- 遮挡浏览器自带的相册按钮 -->
        <view class="browser-button-cover"></view>
        
        <video 
          v-if="showVideo"
          :src="videoSrc" 
          autoplay 
          playsinline 
          muted 
          class="preview-video"
          @error="handleVideoError"
        ></video>
        
        <!-- 扫描框 -->
        <view class="scan-frame">
          <!-- 扫描线动画 -->
          <view class="scan-line" :style="{ top: scanLinePosition + 'px' }"></view>
          
          <!-- 扫描框边角 -->
          <view class="corner top-left"></view>
          <view class="corner top-right"></view>
          <view class="corner bottom-left"></view>
          <view class="corner bottom-right"></view>
        </view>
        
        <!-- 扫描提示文字 -->
        <view class="scan-tip">{{cameraStatusText}}</view>
        
        <!-- 浏览器不支持提示 -->
        <view v-if="showBrowserNotSupported" class="browser-not-supported">
          <view class="error-title">浏览器不支持</view>
          <view class="error-desc">您的浏览器不支持直接访问摄像头</view>
          <view class="suggestions">
            <view>建议：</view>
            <view>1. 使用Chrome、Firefox等现代浏览器</view>
            <view>2. 确保网站使用HTTPS协议</view>
            <view>3. 检查浏览器摄像头权限设置</view>
          </view>
          <button class="retry-btn" @click="retryCamera">重试</button>
        </view>
      </view>
    </view>
    
    <!-- 扫码结果展示 -->
    <view v-if="qrCodeRes" class="result-container">
      <view>扫码成功</view>
    </view>
  </view>
</template>

<script>
let Qrcode = require('../../../../utils/reqrcode.js')
import {
  getInspectionManage
} from '@/api/inspection/inspectionManage.js'

// 二维码优化处理器
const QROptimizer = {
  // 图像预处理
  preprocessImage: function(base64) {
    return new Promise((resolve) => {
      const img = new Image()
      img.src = base64
      img.onload = () => {
        const canvas = document.createElement('canvas')
        const ctx = canvas.getContext('2d')
        canvas.width = img.width
        canvas.height = img.height
        
        // 增强对比度和亮度
        ctx.filter = 'contrast(1.3) brightness(1.1)'
        ctx.drawImage(img, 0, 0)
        
        // 转换为灰度并二值化
        const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height)
        this.binarize(imageData)
        ctx.putImageData(imageData, 0, 0)
        
        resolve(canvas.toDataURL('image/jpeg'))
      }
    })
  },
  
  // 图像二值化处理
  binarize: function(imageData) {
    const data = imageData.data
    for (let i = 0; i < data.length; i += 4) {
      const gray = 0.299 * data[i] + 0.587 * data[i+1] + 0.114 * data[i+2]
      const value = gray > 128 ? 255 : 0
      data[i] = data[i+1] = data[i+2] = value
    }
  },
  
  // 增强版解码
  enhancedDecode: function(base64) {
    return new Promise((resolve) => {
      this.preprocessImage(base64).then(processed => {
        Qrcode.qrcode.decode(processed)
        Qrcode.qrcode.callback = (res) => {
          if (res.indexOf('error') === -1) {
            resolve(res)
          } else {
            // 尝试原始图像解码
            Qrcode.qrcode.decode(base64)
            Qrcode.qrcode.callback = resolve
          }
        }
      })
    })
  }
}

export default {
  data() {
    return {
      qrCodeRes: '',
      videoSrc: '',
      isScanning: false,
      stream: null,
      scanLinePosition: 0,
      scanAnimation: null,
      isCameraReady: false,
      cameraStatusText: '将二维码/条形码放入框内，即可自动扫描',
      permissionDenied: false,
      showVideo: true,
      showBrowserNotSupported: false,
      scanInterval: null,
      lastScanTime: 0,
      scanFrameRect: null
    }
  },
  onShow() {
    this.scanCode();
  },
  mounted() {
    this.initScanAnimation();
  },
  beforeDestroy() {
    if (this.scanAnimation) {
      cancelAnimationFrame(this.scanAnimation);
    }
    this.stopCamera();
    this.stopAutoScan();
  },
  methods: {
    scanCode() {
      // #ifdef APP-PLUS
      this.scanCodeAPP()
      // #endif

      // #ifdef H5
      this.startCustomScanner()
      // #endif
    },
    
    initScanAnimation() {
      const scanFrameHeight = 210;
      const speed = 2;
      
      const animate = () => {
        if (this.scanLinePosition >= scanFrameHeight) {
          this.scanLinePosition = 0;
        } else {
          this.scanLinePosition += speed;
        }
        this.scanAnimation = requestAnimationFrame(animate);
      };
      
      animate();
    },
    
    startCustomScanner() {
      this.isScanning = true;
      this.qrCodeRes = '';
      this.isCameraReady = false;
      this.cameraStatusText = '正在请求摄像头权限...';
      this.showBrowserNotSupported = false;
      this.showVideo = true;
      
      if (!this.checkBrowserSupport()) {
        this.handleBrowserNotSupported();
        return;
      }
      
      this.checkCameraPermission();
    },
    
    checkBrowserSupport() {
      return !!(
        navigator.mediaDevices && 
        navigator.mediaDevices.getUserMedia && 
        window.URL && 
        window.URL.createObjectURL
      );
    },
    
    handleBrowserNotSupported() {
      this.showVideo = false;
      this.showBrowserNotSupported = true;
      this.cameraStatusText = '浏览器不支持摄像头访问';
      this.isCameraReady = false;
    },
    
    checkCameraPermission() {
      if (navigator.permissions && navigator.permissions.query) {
        navigator.permissions.query({ name: 'camera' })
          .then(permissionStatus => {
            if (permissionStatus.state === 'denied') {
              this.handleCameraError('摄像头权限已被拒绝，请在浏览器设置中启用');
              this.permissionDenied = true;
              return;
            }
            this.getUserMediaWithFallback();
          })
          .catch(() => {
            this.getUserMediaWithFallback();
          });
      } else {
        this.getUserMediaWithFallback();
      }
    },
    
    getUserMediaWithFallback() {
      const constraints = {
        video: { 
          facingMode: { ideal: 'environment' },
          width: { ideal: window.innerWidth },
          height: { ideal: window.innerHeight }
        }
      };
      
      navigator.mediaDevices.getUserMedia(constraints)
        .then(stream => {
          this.handleStreamSuccess(stream);
          this.$nextTick(() => {
            const scanFrame = document.querySelector('.scan-frame');
            if (scanFrame) {
              this.scanFrameRect = scanFrame.getBoundingClientRect();
            }
            this.startAutoScan();
          });
        })
        .catch(err => {
          console.warn('后置摄像头访问失败，尝试前置摄像头:', err);
          
          const frontConstraints = {
            video: { 
              facingMode: 'user',
              width: { ideal: window.innerWidth },
              height: { ideal: window.innerHeight }
            }
          };
          
          navigator.mediaDevices.getUserMedia(frontConstraints)
            .then(stream => {
              this.handleStreamSuccess(stream);
              this.$nextTick(() => {
                const scanFrame = document.querySelector('.scan-frame');
                if (scanFrame) {
                  this.scanFrameRect = scanFrame.getBoundingClientRect();
                }
                this.startAutoScan();
              });
            })
            .catch(err2 => {
              console.error('所有摄像头访问失败:', err2);
              this.handleCameraError('无法访问摄像头，请检查设备是否有摄像头并授予权限');
            });
        });
    },
    
    handleStreamSuccess(stream) {
      this.stream = stream;
      this.videoSrc = URL.createObjectURL(stream);
      this.isCameraReady = true;
      
      if (this.stream.getVideoTracks()[0].label.toLowerCase().includes('front')) {
        this.cameraStatusText = '正在使用前置摄像头，建议使用后置摄像头扫码';
      } else {
        this.cameraStatusText = '将二维码放入框内，自动扫描';
      }
    },
    
    startAutoScan() {
      this.stopAutoScan();
      
      const settings = this.getVideoStreamSettings();
      const interval = settings?.height > 720 ? 800 : 500;
      
      this.scanInterval = setInterval(() => {
        const now = Date.now();
        if (now - this.lastScanTime > interval) {
          this.captureAndDecode();
          this.lastScanTime = now;
        }
      }, interval);
    },
    
    getVideoStreamSettings() {
      if (this.stream) {
        const track = this.stream.getVideoTracks()[0];
        return track.getSettings();
      }
      return null;
    },
    
    stopAutoScan() {
      if (this.scanInterval) {
        clearInterval(this.scanInterval);
        this.scanInterval = null;
      }
    },
    
    async captureAndDecode() {
      if (!this.isCameraReady || !this.scanFrameRect) return;
      
      const canvas = document.createElement('canvas');
      const video = document.querySelector('.preview-video');
      
      if (!video || video.readyState !== 4) return;
      
      const frameWidth = this.scanFrameRect.width;
      const frameHeight = this.scanFrameRect.height;
      canvas.width = frameWidth;
      canvas.height = frameHeight;
      
      const ctx = canvas.getContext('2d');
      
      ctx.drawImage(
        video,
        this.scanFrameRect.left, this.scanFrameRect.top, frameWidth, frameHeight,
        0, 0, frameWidth, frameHeight
      );
      
      const base64 = canvas.toDataURL('image/jpeg');
      
      try {
        const codeRes = await QROptimizer.enhancedDecode(base64);
        
        if (codeRes.indexOf('error') === -1) {
          this.stopAutoScan();
          this.stopCamera();
          this.isScanning = false;
          
          let r = this.decodeStr(codeRes);
          this.qrCodeRes = r;
          this.handleScanResult(r);
        } else {
          const qrSize = await this.estimateQRCodeSize(base64);
          if (qrSize < 0.3) {
            this.cameraStatusText = '二维码太小，请靠近些';
          } else if (qrSize > 0.9) {
            this.cameraStatusText = '二维码太大，请离远些';
          }
        }
      } catch (error) {
        console.log("解析失败", error);
      }
    },
    
    estimateQRCodeSize(base64) {
      return new Promise(resolve => {
        const img = new Image();
        img.src = base64;
        img.onload = () => {
          const canvas = document.createElement('canvas');
          canvas.width = img.width;
          canvas.height = img.height;
          const ctx = canvas.getContext('2d');
          ctx.drawImage(img, 0, 0);
          
          const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
          const data = imageData.data;
          
          let activePixels = 0;
          for (let i = 0; i < data.length; i += 4) {
            if (data[i] < 128) activePixels++;
          }
          
          const ratio = activePixels / (canvas.width * canvas.height);
          resolve(Math.min(ratio * 10, 1));
        };
      });
    },
    
    handleCameraError(message) {
      this.cameraStatusText = message;
      this.isCameraReady = false;
      uni.showToast({
        title: message,
        icon: 'none',
        duration: 3000
      });
      this.redirectToWorkbench(); // 摄像头错误跳回工作台
    },
    
    handleVideoError(error) {
      console.error('视频元素错误:', error);
      this.handleCameraError('视频加载失败，请重试');
    },
    
    retryCamera() {
      this.stopCamera();
      if (this.permissionDenied) {
        uni.showModal({
          title: '权限不足',
          content: '请在浏览器设置中允许摄像头权限，然后重试',
          showCancel: false
        });
      } else {
        this.startCustomScanner();
      }
    },
    
    stopCamera() {
      this.stopAutoScan();
      if (this.stream) {
        this.stream.getTracks().forEach(track => {
          track.stop();
        });
        this.stream = null;
      }
      this.videoSrc = '';
      this.isCameraReady = false;
      this.scanFrameRect = null;
    },
    
    cancelScan() {
      this.isScanning = false;
      this.stopCamera();
      this.redirectToWorkbench(); // 取消扫码跳回工作台
    },
    
    scanCodeAPP() {
      uni.scanCode({
        scanType: ['qrCode'],
        onlyFromCamera: true,
        success: (res) => {
          this.qrCodeRes = res.result
          this.handleScanResult(res.result);
        },
        fail: (err) => {
          console.log("扫码失败", err);
          uni.showToast({
            title: '扫码失败，请重试',
            icon: 'none'
          });
          this.redirectToWorkbench(); // APP扫码失败跳回工作台
        }
      })
    },
    
    handleScanResult(result) {
      getInspectionManage(result)
        .then(res => {
          if (res.data.inspectionStatus === "1") {
            let inspectionPoint = res.data.inspectionPoint;
            let inspectionRequirements = res.data.inspectionRequirements;
            let inspectionPointId = res.data.id
            uni.reLaunch({
              url: `/pages/work/inspection/scanSign/index?inspectionPoint=${inspectionPoint}&inspectionRequirements=${inspectionRequirements}&inspectionPointId=${inspectionPointId}`
            });
          } else {
            uni.showToast({
              title: '验证码已失效！',
              icon: 'none'
            });
            this.redirectToWorkbench(); // 验证码失效跳回工作台
          }
        })
        .catch(err => {
          console.log("请求错误", err);
          uni.showToast({
            title: '服务器错误',
            icon: 'none'
          });
          this.redirectToWorkbench(); // 请求错误跳回工作台
        });
    },
    
    // 新增方法：跳转回工作台
    redirectToWorkbench() {
      setTimeout(() => {
        uni.reLaunch({
          url: '/pages/work/index'
        });
      }, 1500); // 1.5秒后跳转，让用户看到提示信息
    },
    
    decodeStr(str) {
      try {
        return decodeURIComponent(escape(str));
      } catch (e) {
        console.warn("解码失败，返回原字符串:", str);
        return str;
      }
    }
  }
}
</script>

<style>
.container {
  padding: 0;
  margin: 0;
  width: 100%;
  min-height: 100vh;
  overflow: hidden;
  background-color: #000;
}

.scanner-container {
  width: 100%;
  height: 100vh;
  position: relative;
  background-color: #000;
}

.scanner-header {
  height: 45px;
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 0 15px;
  background-color: rgba(0, 0, 0, 0.5);
  color: #fff;
}

.back-btn {
  width: 40px;
  height: 40px;
  display: flex;
  align-items: center;
  justify-content: center;
}

.title {
  font-size: 18px;
  font-weight: 500;
}

.empty {
  width: 40px;
}

.camera-preview {
  width: 100%;
  height: calc(100vh - 45px);
  position: relative;
  overflow: hidden;
}

.browser-button-cover {
  position: absolute;
  top: 10px;
  right: 10px;
  width: 45px;
  height: 45px;
  background-color: rgba(0, 0, 0, 0.5);
  z-index: 999;
  pointer-events: none;
}

.preview-video {
  width: 100%;
  height: 100%;
  object-fit: contain;
  background-color: #000;
  position: relative;
  z-index: 0;
}

.camera-preview::before {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background: rgba(0, 0, 0, 0.5);
  z-index: 1;
  clip-path: polygon(
    0% 0%,
    0% 100%,
    calc(50% - 140px) 100%,
    calc(50% - 140px) calc(50% - 105px),
    calc(50% + 140px) calc(50% - 105px),
    calc(50% + 140px) calc(50% + 105px),
    calc(50% - 140px) calc(50% + 105px),
    calc(50% - 140px) 100%,
    100% 100%,
    100% 0%
  );
}

.scan-frame {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 280px;
  height: 210px;
  transform: translate(-50%, -50%);
  border: 1px solid rgba(0, 255, 0, 0.5);
  background-color: rgba(0, 0, 0, 0.3);
  z-index: 10;
}

.scan-line {
  position: absolute;
  left: 0;
  width: 100%;
  height: 2px;
  background-color: #0f0;
  transition: top 0.05s linear;
}

.corner {
  position: absolute;
  width: 20px;
  height: 20px;
  border-color: #0f0;
  border-style: solid;
  background-color: transparent;
}

.top-left {
  top: -1px;
  left: -1px;
  border-width: 3px 0 0 3px;
}

.top-right {
  top: -1px;
  right: -1px;
  border-width: 3px 3px 0 0;
}

.bottom-left {
  bottom: -1px;
  left: -1px;
  border-width: 0 0 3px 3px;
}

.bottom-right {
  bottom: -1px;
  right: -1px;
  border-width: 0 3px 3px 0;
}

.scan-tip {
  position: absolute;
  top: calc(50% + 120px);
  left: 0;
  width: 100%;
  text-align: center;
  color: #fff;
  font-size: 14px;
  padding: 0 20px;
  box-sizing: border-box;
  z-index: 10;
}

.browser-not-supported {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background-color: rgba(0, 0, 0, 0.8);
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  color: #fff;
  padding: 20px;
  box-sizing: border-box;
  text-align: center;
  z-index: 20;
}

.error-title {
  font-size: 20px;
  font-weight: bold;
  margin-bottom: 15px;
  color: #ff5252;
}

.error-desc {
  font-size: 16px;
  margin-bottom: 20px;
}

.suggestions {
  text-align: left;
  margin-bottom: 20px;
  font-size: 14px;
  line-height: 1.6;
}

.retry-btn {
  margin-top: 20px;
  padding: 8px 20px;
  background-color: #2196F3;
  color: white;
  border: none;
  border-radius: 4px;
  font-size: 14px;
}

.result-container {
  padding: 15px;
  background-color: #fff;
  min-height: 100vh;
}
</style>