<script lang="ts" setup>
const dialogVisible = ref(false)

const openDialog = () => {
  dialogVisible.value = true
}

const position = ref(0)
const isDragging = ref(false)
const verifyText = ref('Swipe right to verify')
const sliderState = ref<'start' | 'success' | 'error' | 'dragging'>('start')
const styleMap = {
  start: {
    thumbColor: 'var(--color-neutral-1)',
    thumbIcon: 'icon-icon_drag__line_b',
    trackBackground: '#87909e'
  },
  dragging: {
    thumbColor: 'var(--color-neutral-1)',
    thumbIcon: 'icon-icon_drag__line_b',
    trackBackground: 'var(--color-success)'
  },
  success: {
    thumbColor: '#fff',
    thumbIcon: 'icon-icon_confirm_b',
    trackBackground: 'var(--color-success)'
  },
  error: {
    thumbColor: '#fff',
    thumbIcon: 'icon-icon_reject_b',
    trackBackground: '#c7353f'
  }
}
const trackRef = ref<HTMLElement | null>(null)

const getTrackBackground = () => {
  const trackWidth = trackRef.value?.offsetWidth || 320
  const progress = (position.value / (trackWidth - 40)) * 100 // 百分比
  if (sliderState.value === 'start') {
    return styleMap.start.trackBackground // 初始时灰色
  } else if (sliderState.value === 'dragging') {
    return `linear-gradient(90deg, ${styleMap.success.trackBackground} ${progress}%, ${styleMap.start.trackBackground} ${progress}%)`
  } else if (sliderState.value === 'error') {
    return `linear-gradient(90deg, ${styleMap.error.trackBackground} ${progress}%, ${styleMap.start.trackBackground} ${progress}%)`
  }
  return styleMap.success.trackBackground // 成功时整条绿色
}

const startDrag = () => {
  if (sliderState.value === 'success') {
    return
  }

  isDragging.value = true
  document.addEventListener('mousemove', onDrag)
  document.addEventListener('mouseup', stopDrag)
}

const onDrag = (event: MouseEvent) => {
  if (isDragging.value) {
    if (trackRef.value) {
      sliderState.value = 'dragging'
      verifyText.value = 'Swipe right to verify'
      const rect = trackRef.value.getBoundingClientRect()
      const offsetX = event.clientX - rect.left
      position.value = Math.min(Math.max(offsetX, 0), rect.width - 40) // 40是滑块的宽度
    }
  }
}

const emit = defineEmits<{
  verifySuccess: []
}>()
const stopDrag = () => {
  isDragging.value = false
  document.removeEventListener('mousemove', onDrag)
  document.removeEventListener('mouseup', stopDrag)

  if (trackRef.value) {
    const trackWidth = trackRef.value.offsetWidth
    if (position.value >= trackWidth - 40) {
      sliderState.value = 'success'
      verifyText.value = 'Verification successful'
      setTimeout(() => {
        dialogVisible.value = false
        emit('verifySuccess')
      }, 500)
    } else {
      sliderState.value = 'error'
      verifyText.value = 'Verification failed'
      setTimeout(() => {
        sliderState.value = 'start'
        verifyText.value = 'Swipe right to verify'
        position.value = 0
      }, 3000)
    }
  }
}

const moveSlider = (event: MouseEvent) => {
  if (sliderState.value !== 'success') {
    onDrag(event)
  }
}

const clearData = () => {
  sliderState.value = 'start'
  verifyText.value = 'Swipe right to verify'
  position.value = 0
}
defineExpose({
  openDialog
})
</script>

<template>
  <el-dialog
    top="30vh"
    destroy-on-close
    :close-on-click-modal="false"
    :close-on-press-escape="false"
    @closed="clearData"
    v-model="dialogVisible"
    width="400"
    class="slide-verify-dialog"
  >
    <div class="content">
      <p>Please drag the slider below to complete the</p>
      <p>verification to ensure normal access</p>
      <div class="slider-container">
        <div
          class="slider-track"
          :style="{ background: getTrackBackground() }"
          @click="moveSlider"
          ref="trackRef"
        >
          {{ verifyText }}
          <div
            class="slider-thumb"
            :style="{ left: `${position}px`, borderColor: styleMap[sliderState].trackBackground }"
            @mousedown="startDrag"
          >
            <span
              v-if="sliderState === 'start' || sliderState === 'dragging'"
              class="font_family"
              :style="{ color: styleMap[sliderState].thumbColor }"
              :class="[styleMap[sliderState].thumbIcon]"
            ></span>
            <span
              v-else
              class="font_family other-state"
              :style="{
                color: styleMap[sliderState].thumbColor,
                backgroundColor: styleMap[sliderState].trackBackground
              }"
              :class="[styleMap[sliderState].thumbIcon]"
            ></span>
          </div>
        </div>
      </div>
    </div>
  </el-dialog>
</template>

<style lang="scss" scoped>
.content {
  padding: 40px 0;
  text-align: center;
  & > p {
    line-height: 21px;
  }
}

.slider-container {
  width: 320px;
  margin: 16px auto 0;
  text-align: center;
  user-select: none;
}
.slider-track {
  position: relative;
  width: 100%;
  height: 40px;
  padding: 1px;
  background: #868f9d;
  border-radius: 6px;
  line-height: 38px;
  color: #fff;
}
.slider-thumb {
  position: absolute;
  top: 0px;
  left: 10px;
  width: 40px;
  height: 40px;
  background: #fff;
  cursor: pointer;
  border-radius: 6px;
  border: 1px solid #868f9d;
  .font_family {
    font-size: 14px;
    &.other-state {
      height: 16px;
      width: 16px;
      padding: 1px;
      border-radius: 50%;
      font-size: 14px;
    }
  }
}
</style>

<style lang="scss">
.slide-verify-dialog {
  .el-dialog__header {
    display: none;
  }
  .el-dialog__body {
    padding: 0;
  }
}
</style>
