<template>
  <view class="captcha-container" id="container">
    <view class="font-title">请通过滑块验证</view>
    <view class="captcha-image" style="position: relative; width: 100%; height: 400rpx; overflow: hidden;">
      <image :src="bgImage" class="bg-image" mode="widthFix" @load="init" />
      <view class="overlay" :style="{ width: containerWidth + 'rpx', height: containerHeight + 'rpx' }">
        <view
          class="hole"
          :style="{
            top: originY + 'rpx',
            left: originX + 'rpx',
            width: pieceSize + 'rpx',
            height: pieceSize + 'rpx',
            clipPath: clipPath,
            transform: 'translate(-50%, -50%)',
            backgroundColor: 'rgba(0,0,0,0.6)'
          }"
        ></view>

        <view
          class="piece"
          :style="{
            top: originY + 'rpx',
            left: offsetX + 'rpx',
            width: pieceSize + 'rpx',
            height: pieceSize + 'rpx',
            backgroundImage: `url(${bgImage})`,
            backgroundSize: containerWidth + 'rpx ' + containerHeight + 'rpx',
            backgroundPosition: `-${originX+20}rpx -${originY+13}rpx`,
            clipPath: clipPath,
            transform: 'translate(-50%, -50%)'
          }"
        ></view>
      </view>
    </view>

    <view class="slider-bar">
      <view class="slider-bar-font">向右滑动滑块填充拼图</view>
      <view
        class="slider-button"
        ref="btn"
        @touchstart="onStart"
        @touchmove="onMove"
        @touchend="onEnd"
        :style="{ left: offsetX + 'rpx', maxWidth: (containerWidth - pieceSize) + 'rpx' }"
      >
        <image
          src="https://www.focusnu.com/media/directive/login/right.png"
          style="width: 50rpx; height: 50rpx;"
          mode="widthFix"
        />
      </view>
    </view>
  </view>
</template>

<script setup>
import { ref, onMounted, nextTick, getCurrentInstance } from 'vue'

const emit = defineEmits(['success'])

const pieceSizePx = 50
const pieceSize = pieceSizePx * 2
const tolerance = 20

const containerWidth = ref(400)
const containerHeight = ref(400)

const originX = ref(0)
const originY = ref(0)
const offsetX = ref(0)
const dragging = ref(false)
const startX = ref(0)

const bgImage = ref('')

const instance = getCurrentInstance()

function getPuzzlePiecePath(size) {
  const s = size
  return `
    M${10 * 2} 0
    h${s / 3 - 10 * 2}
    a${10 * 2} ${10 * 2} 0 0 1 0 ${20 * 2}
    h${s / 3}
    a${10 * 2} ${10 * 2} 0 0 0 0 -${20 * 2}
    h${s / 3 - 10 * 2}
    v${s / 3 - 10 * 2}
    a${10 * 2} ${10 * 2} 0 0 1 -${20 * 2} 0
    v${s / 3}
    a${10 * 2} ${10 * 2} 0 0 0 ${20 * 2} 0
    v${s / 3 - 10 * 2}
    h-${s / 3 - 10 * 2}
    a${10 * 2} ${10 * 2} 0 0 1 0 -${20 * 2}
    h-${s / 3}
    a${10 * 2} ${10 * 2} 0 0 0 0 ${20 * 2}
    h-${s / 3 - 10 * 2}
    z
  `
}

const clipPath = `path('${getPuzzlePiecePath(pieceSize)}')`

function init() {
  nextTick(() => {
    if (!instance) {
      console.error('无法获取组件实例')
      return
    }
    uni.createSelectorQuery()
      .in(instance.proxy)
      .select('.bg-image')
      .boundingClientRect(data => {
        if (!data) {
          console.error('无法获取图片尺寸')
          return
        }
        containerWidth.value = data.width * 2
        containerHeight.value = data.height * 2

        originX.value = Math.random() * (containerWidth.value - pieceSize * 2) + pieceSize
        if (originX.value < 100) originX.value = 100
		if (originX.value > 400) originX.value = 400
        originY.value = containerHeight.value / 2
        offsetX.value = 0
      })
      .exec()
  })
}

function onStart(e) {
  dragging.value = true
  startX.value = e.touches[0].clientX * 2
}

function onMove(e) {
  if (!dragging.value) return
  const clientX = e.touches[0].clientX * 2
  let dx = clientX - startX.value
  dx = Math.max(0, Math.min(dx, containerWidth.value - pieceSize))
  offsetX.value = dx
}

function onEnd() {
  dragging.value = false
  if (Math.abs(offsetX.value - originX.value) < tolerance) {
    uni.showToast({
      title: '验证成功',
      icon: 'none',
      duration: 2000
    })
	// console.log("????", originX.value)
    emit('success')
  } else {
    offsetX.value = 0
    uni.showToast({
      title: '验证失败',
      icon: 'none',
      duration: 2000
    })
  }
}

onMounted(() => {
  const images = [
    'https://www.focusnu.com/media/directive/login/0.png',
    'https://www.focusnu.com/media/directive/login/1.png',
    'https://www.focusnu.com/media/directive/login/2.png',
    // 'https://www.focusnu.com/media/directive/login/3.png'
  ]
  bgImage.value = images[Math.floor(Math.random() * images.length)]
  console.log('加载图片:', bgImage.value)
})
</script>

<style scoped lang="scss">
.captcha-container {
  user-select: none;
  background-color: #fff;
  width: 600rpx;
  height: 700rpx;
  margin: 0 auto;
  border-radius: 30rpx;
  overflow: hidden;
  padding: 0 30rpx;
}

.captcha-image {
  position: relative;
  overflow: hidden;
}

.bg-image {
  position: relative;
  z-index: 1;
  display: block;
  width: 100%;
  height: 100%;
}

.overlay {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  z-index: 100;
  pointer-events: none;
}

.hole,
.piece {
  position: absolute;
  z-index: 101;
  box-shadow: 0 0 6rpx rgba(0, 0, 0, 0.4);
}

.hole {
  background-color: rgba(0, 0, 0, 0.3);
}

.piece {
  background-repeat: no-repeat;
  background-size: cover;
  cursor: grab;
}

.slider-bar {
  position: relative;
  height: 100rpx;
  margin-top: 0rpx;
  background: rgb(245, 246, 252);
  width: 540rpx;
  display: flex;
  justify-content: center;
  align-items: center;

  .slider-bar-font {
    color: rgb(169, 169, 171);
    font-size: 28rpx;
  }
}

.slider-button {
  position: absolute;
  top: 0rpx;
  left: 0;
  width: 100rpx;
  height: 100rpx;
  background: #fff;
  box-shadow: 0 0 20rpx rgba(0, 0, 0, 0.2);
  user-select: none;
  border-radius: 10rpx;
  border: 3rpx solid rgb(139, 218, 202);
  display: flex;
  justify-content: center;
  align-items: center;
}

.font-title {
	width: 100%;
	display: flex;
	justify-content: center;
	align-items: center;
	height: 100rpx;
	font-size: 35rpx;
	font-weight: 700;
}
</style>
