<template>
  <el-input v-bind="$attrs" v-model="internalValue" @input="handleInput" @blur="handleBlur" :placeholder="placeholder"
    :disabled="disabled" type="text">

    <template slot="prepend" v-if="prepend">
      {{ prepend }}
    </template>
  </el-input>
</template>

<script>
export default {
  name: 'DecimalInput',
  props: {
    value: {
      type: [Number, String],
      default: ''
    },
    decimalDigits: {
      type: Number,
      default: 6
    },
    placeholder: {
      type: String,
      default: '请输入'
    },
    disabled: {
      type: Boolean,
      default: false
    },
    prepend: {
      type: String,
      default: ''
    },
  },
  data() {
    return {
      internalValue: this.value !== null && this.value !== undefined ? String(this.value) : '',
      oldValue: null,
      oldPattern: null,
      isNA: this.value !== null && this.value !== undefined ? /^NA$/i.test(String(this.value).toUpperCase()) : false,
      patternRules: [
        { name: 'NA', pattern: /^NA$/i, inputPattern: /^N?A?$/i },
        { name: 'FRACTION', pattern: /^\d+(\/\d+)*$/, inputPattern: /^(\d+\/?)*$/ }
      ]
    };
  },
  watch: {
    value: {
      handler(newVal) {
        if (newVal === '' || newVal == null) {
          this.internalValue = '';
          this.oldValue = null;
          this.oldPattern = null;
          this.isNA = false;
        } else {
          const strVal = String(newVal);
          this.internalValue = strVal;
          this.isNA = /^NA$/i.test(strVal.toUpperCase());
          this.updateOldValue(strVal);
        }
      },
      immediate: true
    }
  },
  methods: {
    updateOldValue(val) {
      for (const rule of this.patternRules) {
        if (rule.pattern.test(val)) {
          this.oldValue = val;
          this.oldPattern = rule;
          return true;
        }
      }
      return false;
    },

    getMatchingRule(val) {
      for (const rule of this.patternRules) {
        if (rule.inputPattern.test(val)) {
          return rule;
        }
      }
      return null;
    },

    handleInput(val) {
      if (val === '') {
        this.internalValue = '';
        this.isNA = false;
        this.$emit('input', '');
        return;
      }

      // 检查是否已经输入了完整的NA
      if (this.isNA) {
        // 如果已经输入了NA，无论输入什么，都保持NA不变
        this.internalValue = 'NA';
        this.$emit('input', 'NA');
        return;
      }

      const upperVal = val.toUpperCase();
      let cleaned = val;
      let matchedRule = null;
      
      // 检查是否匹配特殊模式（NA或FRACTION）
      // 优先检查完整的NA模式
      if (/^NA$/i.test(upperVal)) {
        matchedRule = { name: 'NA', pattern: /^NA$/i, inputPattern: /^N?A?$/i };
        cleaned = upperVal;
        this.isNA = true;
      } else if (upperVal === 'N' || upperVal === 'A') {
        // 部分匹配NA模式
        matchedRule = { name: 'NA', pattern: /^NA$/i, inputPattern: /^N?A?$/i };
        cleaned = upperVal;
      } else {
        // 检查FRACTION模式
        matchedRule = this.getMatchingRule(val);
      }
      
      if (matchedRule) {
        if (matchedRule.name === 'FRACTION') {
          cleaned = val.replace(/[^\d/]/g, '');
          const parts = cleaned.split('/');
          const validParts = [];
          for (let i = 0; i < parts.length; i++) {
            if (parts[i] !== '' || i === parts.length - 1) {
              validParts.push(parts[i]);
            }
          }
          cleaned = validParts.join('/');
        } else {
          cleaned = upperVal;
        }
      } else {
        // 处理数字和小数点输入
        cleaned = val
          .replace(/[^\d.-]/g, '')
          .replace(/^(-)\1+/, '$1');

        // 确保只有一个小数点
        const firstDotIndex = cleaned.indexOf('.');
        if (firstDotIndex !== -1) {
          const before = cleaned.slice(0, firstDotIndex);
          const after = cleaned.slice(firstDotIndex + 1).replace(/\./g, '');
          cleaned = before + '.' + after;
        }

        // 处理小数点位数限制
        if (this.decimalDigits > 0 && cleaned.includes('.')) {
          const [intPart, decPart = ''] = cleaned.split('.');
          cleaned = intPart + '.' + decPart.slice(0, this.decimalDigits);
        } else if (this.decimalDigits === 0) {
          cleaned = cleaned.split('.')[0];
        }

        // 处理以小数点开头的情况
        if (cleaned === '.') cleaned = '0.';
        else if (cleaned === '-.') cleaned = '-0.';
        else if (cleaned.startsWith('.')) cleaned = '0' + cleaned;
        else if (cleaned.startsWith('-.')) cleaned = '-0.' + cleaned.slice(2);

        // 处理整数部分的前导零
        if (cleaned.includes('.')) {
          const [int, dec] = cleaned.split('.');
          let newInt = int;
          if (/^-?0+\d/.test(int)) {
            newInt = int.replace(/^-?0+(\d)/, '$1');
          } else if (int === '' || int === '-') {
            newInt = int + '0';
          } else if (int === '00' || /^-00+$/.test(int)) {
            newInt = int.startsWith('-') ? '-0' : '0';
          }
          cleaned = newInt + '.' + dec;
        } else {
          if (/^-?0+\d/.test(cleaned)) {
            cleaned = cleaned.replace(/^-?0+(\d)/, '$1');
          } else if (cleaned === '00' || /^-00+$/.test(cleaned)) {
            cleaned = cleaned.startsWith('-') ? '-0' : '0';
          }
        }
      }

      this.internalValue = cleaned;

      // 处理emit值
      if (cleaned === '' || cleaned === '-') {
        this.$emit('input', cleaned === '-' ? '-' : '');
      } else if (matchedRule && matchedRule.name !== 'FRACTION') {
        this.$emit('input', cleaned);
      } else if (cleaned.includes('/')) {
        this.$emit('input', cleaned);
      } else if (cleaned.includes('.')) {
        // 对于包含小数点的情况，先emit字符串以保持小数点
        this.$emit('input', cleaned);
      } else if (matchedRule && matchedRule.name === 'FRACTION') {
        // 对于FRACTION模式的整数，保持字符串形式以支持后续输入斜杠
        this.$emit('input', cleaned);
      } else {
        // 对于纯数字，转换为数字
        const num = parseFloat(cleaned);
        this.$emit('input', isNaN(num) ? '' : num);
      }
    },

    handleDecimalDigits(val) {
      const actVal = val || this.internalValue;
      let finalValue = actVal.trim();

      if (finalValue === '' || finalValue === '-') {
        return '';
      }

      const num = parseFloat(finalValue);
      if (isNaN(num)) {
        return '';
      }

      let formatted = String(num);
      
      if (!finalValue.includes('.')) {
        formatted = String(Math.floor(num));
      } else {
        const decPart = finalValue.split('.')[1];
        const actualDecimalDigits = decPart.length;
        const displayDecimalDigits = Math.min(actualDecimalDigits, this.decimalDigits);
        formatted = num.toFixed(displayDecimalDigits).replace(/\.?0*$/, '');
      }
      return formatted;
    },

    handleBlur() {
      const val = this.internalValue.trim();
      
      if (val === '') {
        this.oldValue = null;
        this.oldPattern = null;
        this.isNA = false;
        this.$emit('input', '');
        this.$emit('blur', '');
        return;
      }

      const upperVal = val.toUpperCase();
      
      // 检查是否匹配特殊模式
      for (const rule of this.patternRules) {
        if (rule.pattern.test(upperVal)) {
          this.oldValue = upperVal;
          this.oldPattern = rule;
          this.internalValue = upperVal;
          this.isNA = /^NA$/i.test(upperVal);
          this.$emit('input', upperVal);
          this.$emit('blur', upperVal);
          return;
        }
      }

      // 处理分数
      if (val.includes('/')) {
        const parts = val.split('/');
        const validParts = parts.filter(part => part !== '');
        
        if (validParts.length === 0) {
          if (this.oldValue) {
            this.internalValue = this.oldValue;
            this.$emit('input', this.oldValue);
            this.$emit('blur', this.oldValue);
          } else {
            this.internalValue = '';
            this.$emit('input', '');
            this.$emit('blur', '');
          }
          return;
        }
        
        if (validParts.length === 1) {
          const result = validParts[0];
          this.oldValue = result;
          this.oldPattern = this.patternRules.find(r => r.name === 'FRACTION');
          this.internalValue = result;
          this.$emit('input', result);
          this.$emit('blur', result);
          return;
        }
        
        const formattedValue = validParts.join('/');
        this.oldValue = formattedValue;
        this.oldPattern = this.patternRules.find(r => r.name === 'FRACTION');
        this.internalValue = formattedValue;
        this.$emit('input', formattedValue);
        this.$emit('blur', formattedValue);
        return;
      }

      // 处理数字
      let formatted = this.handleDecimalDigits(val);
      this.internalValue = formatted;
      const num = parseFloat(formatted);
      this.$emit('input', isNaN(num) ? '' : num);
      this.$emit('blur', isNaN(num) ? '' : num);
    }
  }
};
</script>
