<template>
  <div class="comp-car-card">
    <el-form ref="formRef" :model="form" :rules="formRules" size="small" label-position="top" @submit.native.prevent>
      <el-row>
        <el-col :span="24">
          <div class="add-vin-btn-wrapper">
            <el-form-item label="VIN列表" prop="vinList">
              <el-button :disabled="!enableAddBtn" class="ccc-add-vin-btn" type="primary" icon="el-icon-plus" plain size="small" @click.stop="clickAddVin">添加VIN码</el-button>
              <!-- <el-button v-if="isInApp" :disabled="!enableAddBtn" class="ccc-add-vin-btn" type="primary" icon="el-icon-camera" plain size="small" @click.stop="handleTakeScan">扫码添加</el-button> -->
            </el-form-item>
          </div>
          <div class="vin-table-wrapper">
            <el-table
              v-loading="loading"
              :data="vinList"
              style="width: 100%">
              <el-table-column
                type="index"
                label="序号"
                width="180"/>
              <el-table-column
                prop="vin"
                label="VIN"
                min-width="320"
              >
                <template slot-scope="scope">
                  <template v-if="scope.row.state === 'readonly'">{{ scope.row.vin }}</template>
                  <template v-else-if="scope.row.state === 'edit'">
                    <el-form :ref="scope.row._formId" :model="scope.row" :rules="vinRules" size="small" label-width="0" @submit.native.prevent>
                      <el-form-item prop="vin" class="ccc-el-form-item" :error="scope.row.error">
                        <el-input :ref="scope.row._inputId" :value="scope.row.vin" clearable maxlength="50" class="ccc-vin-el-input" @input="onVinInput($event, scope.row)"/>
                      </el-form-item>
                    </el-form>
                  </template>
                </template>
              </el-table-column>
              <el-table-column label="操作" width="120">
                <template slot-scope="scope">
                  <el-link v-if="canDelVinRecord(scope)" class="ccc-el-link-del" @click.stop="clickVinItemDel(scope)">删除</el-link>
                </template>
              </el-table-column>
            </el-table>
          </div>
        </el-col>
      </el-row>
    </el-form>
    <comp-confirm
      :show.sync="showDelConfirm"
      :desc="delConfirmDesc"
      :show-cancel-btn="true"
      @on-sure="onDelSure"
    />
    <comp-confirm
      :show.sync="showTipConfirm"
      :desc="tipConfirmDesc"
    />
  </div>
</template>

<script>
import bridge, { isInApp } from '@/utils/bridge'
import { checkVin } from '@/api/iccid'
import { queryUnBindCardByVin, queryBindCardByVin } from '@/api/iccid'
import CompConfirm from '@/components/CompConfirm'
import CompScanCode from '@/components/CompScanCode'

let gid = 0

export default {
  name: 'CompCarCard',
  components: {
    CompConfirm,
    CompScanCode
  },
  props: {
    data: {
      type: Object,
      default: () => ({})
    },
    maxVinLength: {
      type: Number,
      default: 30
    },
    // 特殊业务卡解绑重新封装依据vin获取iccid等信息 SPECIAL
    soucePage: {
      type: String,
      default: () => ''
    },
    // 是否查询绑定的iccid true：已绑定 false：未绑定
    isBind: {
      type: Boolean,
      default: false
    }
  },
  data() {
    const checkVin = (rule, value, callback) => {
      if (value !== '') {
        if (this.checkVin(value)) {
          callback()
        } else {
          callback(new Error('VIN码格式不正确'))
        }
      } else {
        if (this.validVinList.length) {
          callback()
        } else {
          callback(new Error('请输入VIN码'))
        }
      }
    }
    return {
      form: {
        vin: '',
        vinList: []
      },
      formRules: {
        vinList: [
          { type: 'array', required: true, message: '请添加VIN码数据', trigger: '' }
        ]
      },
      vinRules: {
        vin: [
          { required: true, validator: checkVin, trigger: 'blur' }
        ]
      },
      isInApp,
      vinList: [],
      loading: false,
      showDelConfirm: false,
      delConfirmDesc: '确认删除当前行吗？',
      showTipConfirm: false,
      tipConfirmDesc: '',
      inputIsFocus: false
    }
  },
  computed: {
    newAddedVinList() {
      return this.vinList.filter(item => item.state === 'edit')
    },
    validVinList() {
      return this.vinList.filter(item => (item.state === 'edit' ? this.checkVin(item.vin) : (item.vin !== '')))
    },
    enableAddBtn() {
      const ret = (!this.inputIsFocus && !this.loading) || (this.inputIsFocus && !this.form.vin)
      this.$emit('on-canenable', ret)
      return ret
    }
  },
  watch: {
    data() {
      this.updateInternalData()
    },
    vinList(val) {
      if (this._vinListInitMount) {
        this._vinListInitMount = false
        return
      }
      if (val.length) {
        this.$refs.formRef.clearValidate('vinList')
      } else {
        this.$refs.formRef.validateField('vinList')
      }
    }
  },
  created() {
    this._vinListInitMount = true
    this.init()
  },
  methods: {
    errorTips(errMsg) {
      this.showTipConfirm = true
      this.tipConfirmDesc = errMsg
    },

    init() {
      this.updateInternalData()
    },
    updateInternalData() {
      if (typeof this.data === 'object' && this.data !== null) {
        this.form.vinList = []
        this.vinList = Array.isArray(this.data.vinList) ? [...this.data.vinList] : this.getDefaultVinList()
      } else {
        this.form.vinList = []
        this.vinList = this.getDefaultVinList()
      }
    },
    getDefaultVinList() {
      return []
    },

    // 点击添加 ICCID 按钮
    clickAddVin() {
      if (this.vinList.length >= this.maxVinLength) {
        this.errorTips(`最多只能添加${this.maxVinLength}条ICCID数据`)
        return
      }
      const newVin = this.makeVinTemplate()
      newVin.state = 'edit'
      this.vinList.push(newVin)
      this.$nextTick(() => {
        this.$refs[`${newVin._inputId}`].focus()
      })
    },
    // 点击删除 Vin 记录按钮
    clickVinItemDel(scope) {
      this.showDelConfirm = true
      this._curDelIndex = scope.$index
    },
    // 确认删除 ICCID
    onDelSure() {
      this.vinList.splice(this._curDelIndex, 1)
      // 页面渲染完成后检验一下数据
      this.$nextTick(() => {
        this.validateVinListForm2()
      })
    },
    canDelVinRecord(scope) {
      // 卡解绑查询出来的数据不能删除
      if (this.$route.name === 'CardUnbindingStepOne') {
        if (scope.row.state === 'readonly') {
          return false
        }
      }
      return true
    },

    onVinFocus() {
      this.inputIsFocus = true
    },
    // 光标移开 vin 码输入框时的动作
    onVinBlur() {
      this.inputIsFocus = false
      this.$refs.formRef.validateField('vin', errorMsg => {
        if (!errorMsg) {
          this.onVinBlurHandler()
        } else {
          if (this._req) {
            this._req.cancel()
          }
        }
      })
    },
    // 光标移开 vin 码输入框处理
    async onVinBlurHandler() {
      this.loading = true
      const retData = await this.getVinListByVin()
      this.loading = false
      if (retData === 'cancel') {
        return
      }
      const tempVinList = this.vinList.map(item => item.vin)
      const pendingAdd = (retData.vinList || []).filter(item => tempVinList.indexOf(item) === -1)
      const addCount = this.maxVinLength - this.vinList.length

      if (this._preVin === this.form.vin) {
        this.vinList = [
          ...this.normalizeVinList(pendingAdd.slice(0, addCount)),
          ...this.vinList
        ]
      } else {
        this.vinList = [
          ...this.normalizeVinList(pendingAdd.slice(0, addCount)),
          ...this.vinList.filter(item => item.state !== 'readonly')
        ]
      }
      this._preVin = this.form.vin
    },
    // vin 码输入长度限制
    onVinInput($event, cur) {
      if ($event === '' || $event.length <= 17) {
        cur.vin = $event
      }
    },

    checkVin(vin) {
      return vin.length === 17
    },

    async getVinListByVin() {
      let retData = null
      const searchParams = {
        vin: this.form.vin
      }
      try {
        // 接口请求方法
        const reqFuction = this.isBind ? queryBindCardByVin : queryUnBindCardByVin
        // 开始请求接口
        const respData = await reqFuction({
          data: {
            ...searchParams
          },
          cancelToken: this._req.token,
          hideToast: true
        })
        retData = respData || {}
      } catch (e) {
        if (e.code === '_CANCEL_REQUEST_') {
          retData = 'cancel'
        } else {
          // 其他错误需要提示
          this.errorTips(e.message || '系统异常')
        }
      }
      return retData || {}
    },

    // ICCID 记录数据模板
    makeVinTemplate() {
      return {
        vin: '',
        state: 'readonly',
        _formId: gid++,
        _inputId: gid++
      }
    },
    // 标准化远程获取的 ICCID 记录数据
    normalizeVinList(list = []) {
      return list.map(item => {
        const newVin = this.makeVinTemplate()
        newVin.vin = item
        newVin.state = 'readonly'
        return newVin
      })
    },

    async validateForm1(isErrorAnchor = false) {
      this.form.vinList = JSON.parse(JSON.stringify(this.vinList))
      try {
        await this.$refs.formRef.validate()
        return true
      } catch (e) {
        if (isErrorAnchor) {
          this.$refs.formRef.fields.filter(item => item.validateState === 'error')[0].$el.scrollIntoView(true)
        }
        let temp = {
          anchor: () => {
            this.$refs.formRef.fields.filter(item => item.validateState === 'error')[0].$el.scrollIntoView(true)
            temp = null
          }
        }
        throw temp
      }
    },
    async validateVinListForm2(isErrorAnchor = false) {
      const validateVinList = this.newAddedVinList
      for (let i = 0, len = validateVinList.length; i < len; i++) {
        const item = validateVinList[i]
        try {
          await this.$refs[item._formId].validate()
        } catch (e) {
          if (isErrorAnchor) {
            this.$refs[item._inputId].$el.scrollIntoView(true)
          }
          let temp = {
            anchor: () => {
              this.$refs[item._inputId].$el.scrollIntoView(true)
              temp = null
            }
          }
          throw temp
        }
      }
      return true
    },

    // 校验
    async validate(isErrorAnchor = false) {
      try {
        await Promise.all([
          this.validateForm1(),
          this.validateVinListForm2()
        ])
        // 校验输入结果
        await this.checkList()
        return true
      } catch (e) {
        throw e
      }
    },
    /**
     * 接口校验vin的有效性
     */
    async checkList() {
      this.vinList.forEach(vin => {
        this.$set(vin, 'error', '')
      })
      // iccid的集合
      this.iccidList = []
      // 获取校验的数据
      const { checkList } = await checkVin({ vinList: this.vinList.map(vin => vin.vin) })
      // 如果当前校验失败
      if (checkList.some(item => !item.checkResult)) {
        checkList.forEach(check => {
          this.vinList.forEach(vin => {
            if (check.vin === vin.vin && vin.error !== check.errorMsg) {
              this.$set(vin, 'error', check.checkResult ? '' : check.errorMsg)
            }
          })
        })
        throw new Error('接口校验失败')
      }
      // 校验项目
      checkList.forEach(check => {
        this.iccidList.push({
          vin: check.vin,
          iccidList: check.iccidList
        })
      })
    },
    // 获取数据
    getFormData() {
      return {
        vinList: this.vinList.map(item => item.vin)
      }
    },
    // 获取待缓存数据
    getPendingCacheData() {
      return {
        vinList: JSON.parse(JSON.stringify(this.vinList)),
        iccidList: JSON.parse(JSON.stringify(this.iccidList || []))
      }
    },

    /**
     * 扫码添加
     */
    handleScanCallback(code) {
      if (this.vinList.length >= this.maxVinLength) {
        this.errorTips(`最多只能添加${this.maxVinLength}条ICCID数据`)
        return
      }
      const newVin = this.makeVinTemplate()
      newVin.state = 'edit'
      newVin.vin = code
      this.vinList.push(newVin)
    },

    /**
     * 扫码功能
     */
    handleTakeScan() {
      bridge.scanCode(true, code => {
        this.handleScanCallback(code)
      })
    }
  }
}
</script>

<style lang="scss">
.comp-car-card {
  .ccc-vin-input {
    width: 44%;
  }
  .ccc-vin-el-input {
    width: 60%;
  }
  .ccc-el-form-item {
    .el-form-item__error {
      left: 62%;
      top: 50%;
      transform: translateY(-50%);
    }
  }
  .add-vin-btn-wrapper {
    margin-bottom: 8px;
    .ccc-add-vin-btn {
      border-color: #B9CFFF;
      color: #2A68FF;
      background: #F5F7FF;
      &:hover {
        border-color: #5489FF;
        background: #F5F7FF;
        color: #5489FF;
      }
    }
  }
  .vin-table-wrapper {
    .el-form-item {
      margin-bottom: 0 !important;
    }
    .ccc-el-link-del {
      font-size: 14px;
      color: #2A68FF;
      &:hover {
        &:after {
          display: none;
        }
      }
    }
  }
}
</style>
