<template>
  <div class="verify-title">
    Enter Verification Code
    <div class="countdown" @click="handleResend">
      {{ countdown <= 0 ? 'Resend' : countdown + 's' }}
    </div>
  </div>
  <div class="verify-subtitle">We’ve sent an code to your email {{ email }}</div>
  <div class="captcha">
    <input
      v-for="(c, index) in getCtData"
      :key="index"
      type="text"
      v-model="getCtData[index]"
      :ref="(el) => setInputRef(el, index)"
      inputmode="numeric"
      pattern="[0-9]*"
      @input="(e) => onInput(e.target.value, index)"
      @keydown="(e) => onKeydown(e, index)"
      @keypress="(e) => onKeypress(e)"
      @focus="onFocus"
      @pause="onPause"
      :disabled="loading"
    />
  </div>
  <div class="policy">
    <van-checkbox v-model="agreePolicy" shape="square">
      I agree to all Terms, Privacy Policy, and Fees.
    </van-checkbox>
  </div>
  <div class="btn" @click="handleConfirmCaptcha">Confirm</div>
</template>
<script setup lang="ts">
import { ref, computed, watch, onMounted, nextTick } from 'vue'
import { showToast } from 'vant'

// Props
const props = defineProps({
  ct: {
    type: Array,
    required: true
  },
  email: {
    type: String,
    required: true
  }
})

const agreePolicy = ref(false)
// Emits
const emit = defineEmits(['nextStep'])

// Reactive data
const loading = ref(false)
const timeout = ref(null)
const inputRefs = ref([])
const getCtData = ref([...props.ct])

// Computed
const ctSize = computed(() => getCtData.value.length)
const cIndex = computed(() => {
  let i = getCtData.value.findIndex((item) => item === '')
  i = (i + ctSize.value) % ctSize.value
  return i
})
const lastCode = computed(() => getCtData.value[ctSize.value - 1])

const countdown = ref(60)
const handleCountdown = () => {
  const timer = setInterval(() => {
    countdown.value--
    if (countdown.value <= 0) {
      clearInterval(timer)
    }
  }, 1000)
}

const handleSendVerifyCode = () => {
  handleCountdown()
}

const handleResend = () => {
  if (countdown.value > 0) return
  countdown.value = 60
  handleSendVerifyCode()
}

const handleConfirmCaptcha = () => {
  let password = getCtData.value.map((item) => item).join('')
  // 验证验证码
  if (!agreePolicy.value) {
    showToast('please agree to all terms, privacy policy, and fees.')
    return
  }
  if (password.length !== 5) {
    showToast('please enter the correct verification code.')
    return
  }
  // 验证验证码
  new Promise((resolve, reject) => {
    console.log('pwd', password)
    resolve(true)
  })
    .then(() => {
      // showToast('verification code is correct.')
      emit('nextStep', 'password')
    })
    .catch(() => {
      showToast('verification code is incorrect.')
    })
}

// Methods
const setInputRef = (el, index) => {
  if (el) {
    inputRefs.value[index] = el
  }
}

const onInput = (val, index) => {
  clearTimeout(timeout.value)
  timeout.value = setTimeout(() => {
    // val = val.replace(/[^0-9]/g, '');
    val = String(val).replace(/\D/g, '')
    getCtData.value[index] = val
    if (index == ctSize.value - 1) {
      getCtData.value[ctSize.value - 1] = val[0] // 最后一个码，只允许输入一个字符。
    } else if (val.length > 1) {
      let i = index
      for (i = index; i < ctSize.value && i - index < val.length; i++) {
        getCtData.value[i] = val[i]
      }
      resetCaret()
    } else if (!(val + '')) {
      getCtData.value[index] = ''
    }
  }, 10)
}

const onPause = () => {}

// 重置光标位置。
const resetCaret = () => {
  nextTick(() => {
    inputRefs.value[ctSize.value - 1]?.focus()
  })
}

const onFocus = () => {
  // 监听 focus 事件，将光标重定位到"第一个空白符的位置"。
  let index = getCtData.value.findIndex((item) => item === '')
  index = (index + ctSize.value) % ctSize.value
  inputRefs.value[index]?.focus()
}

const onKeypress = (e) => {
  // 只允许输入数字0-9
  const char = String.fromCharCode(e.which)
  if (!/[0-9]/.test(char)) {
    e.preventDefault()
  }
}

const onKeydown = (e, index) => {
  // 处理删除键
  if (e.key === 'Backspace' || e.key === 'Delete') {
    const val = e.target.value
    if (val === '') {
      // 删除上一个input里的值，并对其focus。
      if (index > 0) {
        getCtData.value[index - 1] = ''
        inputRefs.value[index - 1]?.focus()
      }
    }
  }
  // 阻止其他非数字字符
  else if (
    e.key &&
    !/[0-9]/.test(e.key) &&
    ![
      'Backspace',
      'Delete',
      'Tab',
      'Enter',
      'ArrowLeft',
      'ArrowRight',
      'ArrowUp',
      'ArrowDown'
    ].includes(e.key)
  ) {
    e.preventDefault()
  }
}

// const sendCaptcha = () => {
//   let password = getCtData.value.map((item) => item).join('')
//   emit('sendCaptcha', password)
// }

const reset = () => {
  // 重置。一般是验证码错误时触发。
  getCtData.value = ['', '', '', '', '']
  resetCaret()
}

// Watchers
watch(cIndex, () => {
  resetCaret()
})

// watch(lastCode, (newVal, oldVal) => {
//   if (newVal && newVal != oldVal) {
//     inputRefs.value[ctSize.value - 1]?.blur()
//     sendCaptcha()
//   }
// })

// Lifecycle
onMounted(() => {
  resetCaret()
  handleSendVerifyCode()
})

// Expose methods for parent component
defineExpose({
  reset
})
</script>

<style scoped lang="less">
.captcha {
  display: flex;
  column-gap: 3rem;
}
input {
  width: 11rem;
  height: 12.6rem;
  border: 0.2rem solid #fff;
  border-radius: 2rem;
  text-align: center;
  font-size: 4.8rem;
  line-height: 12.6rem;
  outline: none;
  background: none;
}

.msg {
  text-align: center;
}

.verify-title {
  font-size: 4.8rem;
  position: relative;
  .countdown {
    position: absolute;
    right: 0;
    top: 50%;
    transform: translate(0, -50%);
    font-size: 2.6rem;
    color: #fff;
    font-family: 'satoshiRegular';
  }
}
.verify-subtitle {
  font-size: 2.5rem;
  margin-bottom: 6.4rem;
}
.policy {
  margin-top: 5.95rem;
  :deep(.van-checkbox__icon) {
    font-size: 3rem;
  }
  :deep(.van-checkbox__label) {
    font-size: 2.4rem;
    color: #fff;
    margin-left: 1.68rem;
  }
}

.btn {
  width: 100%;
  height: 10rem;
  background: #000;
  color: white;
  border: none;
  border-radius: 7rem;
  font-size: 4rem;
  margin-bottom: 1.67rem;
  text-align: center;
  line-height: 10rem;
  margin-top: 8.8rem;
}
</style>
