<template>
  <div class="bx-verify-code-input">
    <div class="bx-hairline--bottom">
      <bxs-input
        :placeholder="placeholder"
        v-model.trim="currentCellphone"
        label="手机号"
        type="number"
        :error-message="errorCellphoneMsg"
        @change="cellphoneChange"
        />
    </div>
    <div class="bx-hairline--bottom">
      <bxs-input
        v-bind="$attrs"
        placeholder="请输入验证码"
        :class="{'has-error': errorMessage}"
        :error-message="errorMessage"
        v-model.trim="currentVerifyCode"
        label="验证码"
        type="text"
        autocomplete="one-time-code"
        ref="inputVerifyCode"
        >
        <span
          slot="button"
          v-if="!sliderOpening"
          class="bx-verify-code-input-button"
          @click="handlerGetVerifyCode"
          :class="{ 'bx-verify-code-input-button--getting': !this.btnTextClickable }"
          >
          {{ btnText }}
        </span>
      </bxs-input>
    </div>
    <!-- 滑动验证块 -->
    <div class="bx-verify-code-input-slider">
      <div class="bx-verify-code-input-tip">
        请滑动验证，获取验证码
      </div>
      <div :id="sliderId" />
    </div>
    <!-- 语音验证按钮 -->
    <div
      v-if="(debugVoice || gettingTimes >= 2) && !voiceSliderOpening && !voiceSendSuccess"
      class="bx-verify-code-input-voice"
      :class="{ 'bx-verify-code-input-button--getting': !this.btnVoiceTextClickable }"
      >
      <span @click="handlerGetVerifyVoice">
        {{ voiceText }}
      </span>
    </div>
  </div>
</template>
<script>
import Input from '../input/index'
import { create } from '../utils/index'
import nvcRequest, { resetNvc } from '../utils/alinvc'

let captchaSendUrl
let captchaSendVoiceUrl
const host = window.location.hostname
if (/^.*\.wyins\.net$/.test(host)) {
  ;[captchaSendUrl, captchaSendVoiceUrl] = [
    '//third-api.wyins.net/captcha/send?mobile=',
    '//third-api.wyins.net/captcha/sendVoice?mobile=',
  ]
} else if (/^.*\.wyins\.net.cn$/.test(host)) {
  ;[captchaSendUrl, captchaSendVoiceUrl] = [
    '//third-api.wyins.net.cn/captcha/send?mobile=',
    '//third-api.wyins.net.cn/captcha/sendVoice?mobile=',
  ]
} else if (/^.*\.com$/.test(host) && host !== 'test.winbaoxian.com') {
  ;[captchaSendUrl, captchaSendVoiceUrl] = [
    '//third-api.winbaoxian.com/captcha/send?mobile=',
    '//third-api.winbaoxian.com/captcha/sendVoice?mobile=',
  ]
} else {
  ;[captchaSendUrl, captchaSendVoiceUrl] = [
    '//third-api.winbaoxian.cn/captcha/send?mobile=',
    '//third-api.winbaoxian.cn/captcha/sendVoice?mobile=',
  ]
}

export default create({
  name: 'verify-code-input',
  model: {
    prop: 'cellphone',
    event: 'input',
  },
  props: {
    debugVoice: {
      type: Boolean,
      default: false,
    },
    debugNvc: {
      type: Object,
      required: false,
    },
    cellphone: {
      type: [String, Number],
      required: true,
    },
    placeholder: {
      type: String,
      default: '请输入手机号码',
    },
    errorMessage: {
      type: String,
      default: '',
    },
  },
  components: {
    [Input.name]: Input,
  },
  data() {
    return {
      requestId: '', // nvc 的请求 ID
      sliderId: '', // 随机生成的元素 id, 验证滑块会显示在该元素内
      errorCellphoneMsg: '',
      currentVerifyCode: '', // 用户输入的验证码
      sliderOpening: false, // 验证滑块是否正在显示
      btnText: '',
      btnTextClickable: true,
      gettingTimes: 0, // 验证码的请求次数
      idGettingCode: null, // 计时器
      texts: {
        initial: '获取验证码',
        noTraceVerify: '验证获取中', // 无痕验证中的文案
        again: '重新获取',
      },
      countDown: 59, // 倒计时数字
      voiceText: '语音验证',
      btnVoiceTextClickable: true,
      voiceSliderOpening: false, // 验证滑块是否正在显示
      voiceSendSuccess: false, // 语音验证码是否成功发送
    }
  },
  computed: {
    currentCellphone: {
      get() {
        return this.cellphone
      },
      set(val) {
        this.$emit('input', val)
      },
    },
  },
  created() {
    this.sliderId = `slider-${new Date().getTime()}${Math.random()
      .toString(32)
      .substring(2)}`
    this.btnText = this.texts.initial
  },
  methods: {
    getVerifyCode() {
      return this.currentVerifyCode
    },
    // 重置组件状态
    resetCountDown(resetTimesAndCode) {
      this.sliderOpening = false
      if (resetTimesAndCode) {
        this.currentVerifyCode = ''
        this.errorCellphoneMsg = ''
        this.gettingTimes = 0
        this.btnText = this.texts.initial
      } else {
        this.btnText = this.texts.again
      }
      this.countDown = 59
      window.clearInterval(this.idGettingCode)
      this.idGettingCode = null
      this.btnTextClickable = true
      // 语音验证码相关
      this.btnVoiceTextClickable = true
      this.voiceSendSuccess = false
      this.voiceSliderOpening = false
      this.voiceText = '语音验证'
    },
    validCellphone() {
      // 手机号非空校验
      if (!this.currentCellphone) {
        this.errorCellphoneMsg = '请输入手机号'
        return false
      }
      // 手机号 11 位数字校验
      if (!/^[0-9]{11}$/.test(String(this.currentCellphone))) {
        this.errorCellphoneMsg = '手机号必须为11位数字'
        return false
      }
      this.errorCellphoneMsg = ''
      return true
    },
    // 如果手机号改变了, 则重置组件状态
    cellphoneChange() {
      this.validCellphone()
      this.resetCountDown(true)
      resetNvc(this.requestId)
    },
    startCountDown() {
      this.btnTextClickable = false
      this.btnText = `重发 (${this.countDown}s)`
      this.idGettingCode = window.setInterval(() => {
        if (this.countDown <= 0) {
          this.resetCountDown(false)
          return
        }
        this.countDown = this.countDown - 1
        this.btnText = `重发 (${this.countDown}s)`
      }, 1000)
    },
    // 获取短信验证码
    handlerGetVerifyCode() {
      if (!this.btnTextClickable) return
      if (!this.validCellphone()) return

      if (window.appBridge) window.appBridge.showLoading(true)
      this.btnTextClickable = false
      this.btnText = '验证获取中'
      this.gettingTimes = this.gettingTimes + 1
      this.requestId =
        new Date().getTime() +
        Math.random()
          .toString(32)
          .substring(2)
      const sliderStartCb = () => {
        this.sliderOpening = true
        if (window.appBridge) window.appBridge.hideLoading()
      }
      nvcRequest(
        this.requestId,
        `${captchaSendUrl}${this.currentCellphone}`,
        `#${this.sliderId}`,
        this.debugNvc,
        // { nvcCode: 400, key1: "code300" },
        sliderStartCb,
      )
        .then(res => {
          if (res.success === false) throw new Error(res.info)
          if (window.appBridge) window.appBridge.hideLoading()
          this.sliderOpening = false
          // 手机号校验通过, 倒计时开始
          this.$toast(res.info || '验证码发送成功')
          this.startCountDown()
          this.$refs.inputVerifyCode.$el.querySelector('input').focus()
        })
        .catch(err => {
          if (window.appBridge) window.appBridge.hideLoading()
          this.$toast(err.message || '发送验证码失败，请稍后再试')
          this.startCountDown()
          this.sliderOpening = false
        })
    },
    // 获取语音验证码
    handlerGetVerifyVoice() {
      if (!this.btnVoiceTextClickable) return
      if (!this.validCellphone()) return

      if (window.appBridge) window.appBridge.showLoading(true)
      this.btnVoiceTextClickable = false
      this.voiceText = '验证获取中'
      this.requestId =
        new Date().getTime() +
        Math.random()
          .toString(32)
          .substring(2)
      const sliderStartCb = () => {
        this.voiceSliderOpening = true
        if (window.appBridge) window.appBridge.hideLoading()
      }
      nvcRequest(
        this.requestId,
        `${captchaSendVoiceUrl}${this.currentCellphone}`,
        `#${this.sliderId}`,
        this.debugNvc,
        sliderStartCb,
      )
        .then(res => {
          if (res.success === false) throw new Error(res.info)
          if (window.appBridge) window.appBridge.hideLoading()
          this.voiceSliderOpening = false
          this.voiceSendSuccess = true
          // 手机号校验通过, 倒计时开始
          this.$toast(res.info || '请留意接听语音验证码')
          this.safeFocusInput()
        })
        .catch(err => {
          if (window.appBridge) window.appBridge.hideLoading()
          this.$toast(err.message || '发送验证码失败，请稍后再试')
          this.voiceText = '语音验证'
          this.btnVoiceTextClickable = true
          this.voiceSliderOpening = false
        })
    },
  },
  safeFocusInput() {
    const inputEle = this.$refs.inputVerifyCode.$el.querySelector('input')
    if (inputEle) {
      inputEle.focus()
    }
  },
  beforeDestroy() {
    window.clearInterval(this.idGettingCode)
  },
})
</script>
<style lang="postcss">
@import './index.css';
@import '../../src/style/alinvc.css';
</style>
