// #ifdef WEB
<template>
  <div :id="uuid">
    <div class="ba-click-captcha" :class="props.class">
      <div v-if="state.loading" class="loading">{{ '加载中' }}</div>
      <div v-else class="captcha-img-box">
        <img
          class="captcha-img"
          @click.prevent="onRecord($event)"
          :src="state.captcha.base64"
          :alt="'验证码加载失败，请点击刷新按钮'"
        />
        <span
          v-for="(item, index) in state.xy"
          :key="index"
          class="step"
          @click="onCancelRecord(index)"
          :style="`left:${parseFloat(item.split(',')[0]) - 13}px;top:${
            parseFloat(item.split(',')[1]) - 13
          }px`"
        >
          {{ index + 1 }}
        </span>
      </div>
      <div class="captcha-prompt" v-if="state.tip">
        {{ state.tip }}
      </div>
      <div v-else class="captcha-prompt">
        请依次点击
        <span
          v-for="(text, index) in state.captcha.text"
          :key="index"
          :class="state.xy.length > index ? 'clicaptcha-clicked' : ''"
        >
          {{ text }}
        </span>
      </div>
      <div class="captcha-refresh-box">
        <div class="captcha-refresh-line captcha-refresh-line-l"></div>
        <uni-icons
          type="loop"
          class="captcha-refresh-btn"
          size="35"
          :title="'Refresh'"
          @click="load"
        />
        <div class="captcha-refresh-line captcha-refresh-line-r"></div>
      </div>
    </div>
    <div class="ba-layout-shade" @click="onClose"></div>
  </div>
</template>

<script setup lang="ts">
import { reactive, computed } from 'vue'
import { getCaptchaData, checkClickCaptcha } from '@/api/common'

interface Props {
  uuid: string
  callback?: (captchaInfo: string) => void
  class?: string
  unset?: boolean
  error?: string
  success?: string
}

const props = withDefaults(defineProps<Props>(), {
  uuid: '',
  callback: () => {},
  class: '',
  unset: false,
  error: '未点中正确区域，请重试！',
  success: '验证成功!',
})

const state: {
  loading: boolean
  xy: string[]
  tip: string
  captcha: {
    id: string
    text: string
    base64: string
    width: number
    height: number
  }
} = reactive({
  loading: true,
  xy: [],
  tip: '',
  captcha: {
    id: '',
    text: '',
    base64: '',
    width: 350,
    height: 200,
  },
})

const load = () => {
  state.loading = true
  getCaptchaData(props.uuid).then((res) => {
    state.xy = []
    state.tip = ''
    state.loading = false
    state.captcha = (res as any).data
  })
}

const onRecord = (event: MouseEvent) => {
  if (state.xy.length < state.captcha.text.length) {
    state.xy.push(event.offsetX + ',' + event.offsetY)
    if (state.xy.length == state.captcha.text.length) {
      const captchaInfo = [
        state.xy.join('-'),
        (event.target as HTMLImageElement).width,
        (event.target as HTMLImageElement).height,
      ].join(';')
      checkClickCaptcha(props.uuid, captchaInfo, props.unset)
        .then((res) => {
          if ((res as any).code == 1) {
            state.tip = props.success
            setTimeout(() => {
              props.callback?.(captchaInfo)
              onClose()
            }, 1500)
          } else {
            state.tip = props.error
            setTimeout(() => {
              load()
            }, 1500)
          }
        })
        .catch(() => {
          state.tip = props.error
          setTimeout(() => {
            load()
          }, 1500)
        })
    }
  }
}

const onCancelRecord = (index: number) => {
  state.xy.splice(index, 1)
}

const onClose = () => {
  document.getElementById(props.uuid)?.remove()
}

const captchaBoxTop = computed(() => (state.captcha.height + 200) / 2 + 'px')
const captchaBoxLeft = computed(() => (state.captcha.width + 24) / 2 + 'px')

load()
</script>

<style scoped lang="scss">
.ba-click-captcha {
  padding: 12px;
  border: 1px solid #f2f6fc;
  background-color: #fff;
  position: fixed;
  z-index: 9999991;
  left: calc(50% - v-bind('captchaBoxLeft'));
  top: calc(50% - v-bind('captchaBoxTop'));
  border-radius: 10px;
  box-shadow: 0 0 0 1px hsla(0, 0%, 100%, 0.3) inset, 0 0.5em 1em rgba(0, 0, 0, 0.6);
  .loading {
    color: #909399;
    width: 350px;
    text-align: center;
    line-height: 200px;
  }
  .captcha-img-box {
    position: relative;
    .captcha-img {
      width: v-bind('state.captcha.width') px;
      height: v-bind('state.captcha.height') px;
      border: none;
      cursor: pointer;
    }
    .step {
      box-sizing: border-box;
      position: absolute;
      width: 20px;
      height: 20px;
      line-height: 20px;
      font-size: 13px;
      font-weight: bold;
      text-align: center;
      color: #fff;
      border: 1px solid #f2f6fc;
      background-color: #409eff;
      border-radius: 30px;
      box-shadow: 0 0 10px #fff;
      user-select: none;
      cursor: pointer;
    }
  }
  .captcha-prompt {
    height: 40px;
    line-height: 40px;
    font-size: 14px;
    text-align: center;
    color: #909399;
    span {
      margin-left: 10px;
      font-size: 16px;
      font-weight: bold;
      color: #f56c6c;
      &.clicaptcha-clicked {
        color: #409eff;
      }
    }
  }
  .captcha-refresh-box {
    position: relative;
    margin-top: 10px;
    .captcha-refresh-line {
      position: absolute;
      top: 16px;
      width: 150px;
      height: 1px;
      background-color: #ccc;
    }
    .captcha-refresh-line-l {
      left: 5px;
    }
    .captcha-refresh-line-r {
      right: 5px;
    }
    .captcha-refresh-btn {
      cursor: pointer;
      display: block;
      margin: 0 auto;
      width: 32px;
      height: 32px;
      font-size: 32px;
      color: #909399;
    }
  }
}

.ba-layout-shade {
  position: fixed;
  top: 0;
  left: 0;
  height: 100vh;
  width: 100vw;
  background-color: rgba(0, 0, 0, 0.5);
  z-index: 9999990;
}
</style>
// #endif
