<template>
  <div class="kole-card">
    <div class="kole-card-field" :class="{ 'is-focus': focused, 'is-valid': valid, 'is-invalid': invalid }">
      <input
        class="kole-card-input"
        :value="display"
        inputmode="numeric"
        maxlength="23"
        :placeholder="placeholder"
        @input="onInput"
        @focus="focused = true"
        @blur="focused = false"
      />
      <span class="kole-card-type" :class="{ unknown: !cardType }">{{ cardType || '未知' }}</span>
    </div>
    <div class="kole-card-tip" :class="tipClass">{{ tipText }}</div>
  </div>
</template>

<script setup>
import { ref, computed } from 'vue';

const props = defineProps({
  modelValue: { type: String, default: '' },
  placeholder: { type: String, default: '请输入银行卡号' }
});
const emit = defineEmits(['update:modelValue']);
const digits = ref(props.modelValue.replace(/\D/g, ''));
const focused = ref(false);

const display = computed(() => digits.value.replace(/(.{4})/g, '$1 ').trim());
const cardType = computed(() => {
  const v = digits.value;
  if (/^4/.test(v)) return 'Visa';
  if (/^5[1-5]/.test(v)) return 'MasterCard';
  if (/^62/.test(v)) return '银联';
  if (/^3[47]/.test(v)) return 'AmEx';
  if (/^35/.test(v)) return 'JCB';
  return '';
});
const luhn = computed(() => {
  const v = digits.value;
  let sum = 0, alt = false;
  for (let i = v.length - 1; i >= 0; i--) {
    let n = parseInt(v[i], 10);
    if (alt) { n *= 2; if (n > 9) n -= 9; }
    sum += n; alt = !alt;
  }
  return sum % 10 === 0;
});
const valid = computed(() => digits.value.length >= 13 && luhn.value);
const invalid = computed(() => digits.value.length >= 13 && !luhn.value);
const tipClass = computed(() => (valid.value ? 'valid' : invalid.value ? 'invalid' : ''));
const tipText = computed(() => {
  if (digits.value.length === 0) return '支持 Visa / MasterCard / 银联等';
  if (valid.value) return '卡号校验通过';
  if (invalid.value) return '卡号未通过 Luhn 校验';
  return '继续输入卡号…';
});

function onInput(e) {
  digits.value = e.target.value.replace(/\D/g, '').slice(0, 19);
  e.target.value = display.value;
  emit('update:modelValue', digits.value);
}
</script>

<style src="./BankCardInput.css"></style>
