<template>
  <div>
    <template v-if="!visible">
      <a-input
        :class="[style && Object.keys(style).length > 0 ? 'customStyle' : '']"
        :style="{ width: width }"
        readonly
        v-model:value="labelRef"
        :placeholder="placeholder"
        :maxlength="parseInt(maxlength as string)"
        :addonBefore="addonBefore"
        :addonAfter="addonAfter"
        :disabled="disabled"
        @click="handleClick"
        @change="handleChange"
        :size="size"
        :bordered="bordered"
      >
        <template #prefix v-if="prefix">
          <Icon :icon="prefix" />
        </template>
        <template #suffix v-if="suffix">
          <Icon :icon="suffix" />
        </template>
      </a-input>
    </template>
    <template v-if="visible">
      <a-input-number
        :class="[style && Object.keys(style).length > 0 ? 'customStyle' : '']"
        ref="inputNumRef"
        v-model:value="valueRef"
        :placeholder="placeholder"
        :maxlength="parseInt(maxlength as string)"
        :addonBefore="addonBefore"
        :addonAfter="addonAfter"
        :disabled="disabled"
        @blur="handleBlur"
        @change="handleChange"
        :style="{ width: width }"
        :size="size"
        :bordered="bordered"
        :formatter="formatterVal"
        :parser="formatterVal"
      >
        <template #prefix v-if="prefix">
          <Icon :icon="prefix" />
        </template>
        <template #suffix v-if="suffix">
          <Icon :icon="suffix" />
        </template>
      </a-input-number>
    </template>
  </div>
</template>
<script lang="ts" setup>
  import { ref, nextTick, watch, inject, toRaw, computed } from 'vue';
  import nzhcn from 'nzh/cn';
  import JBC from 'jsbi-calculator';
  import { sum, mean, max, min } from 'lodash-es';
  import { camelCaseString, moneyChineseData, formatter } from '/@/utils/event/design';
  import { Icon } from '/@/components/Icon';
  import { ComputationalConfig } from '/@/components/Designer/src/types';

  const props = defineProps({
    value: {
      type: [Number, String],
      default: 0,
    },
    maxlength: { type: [String, Number] },
    placeholder: { type: String },
    addonBefore: { type: String },
    addonAfter: { type: String },
    prefix: { type: String },
    suffix: { type: String },
    disabled: { type: Boolean },
    computationalConfig: { type: Array as PropType<ComputationalConfig[]> },
    computationalConfigValue: { type: String },
    index: { type: Number },
    size: { type: String },
    bordered: {
      type: Boolean,
      default: true,
    },
    decimals: Number,
    style: Object,
    width: String,
  });

  const inputNumRef = ref();
  const valueRef = ref(0);

  const labelRef = ref(`${nzhcn.encodeB(valueRef.value)}元`);

  const visible = ref(false);
  const formModel = inject<any>('formModel', null); // 注入表单数据
  const isCamelCase = inject<boolean>('isCamelCase', false);
  const { calculator } = JBC;

  const emit = defineEmits(['update:value', 'change', 'blur']);

  watch(
    () => props.value,
    (val) => {
      valueRef.value = Number(val);
    },
    {
      immediate: true,
    },
  );

  watch(
    () => valueRef.value,
    (val) => {
      labelRef.value = moneyChineseData(val);
      emit('update:value', val);
      emit('change', val);
    },
    // {
    //   immediate: true,
    // },
  );

  watch(
    () => formModel,
    () => {
      if (!toRaw(props)?.computationalConfig) return;
      let expressionStr = '';
      for (let config of toRaw(props).computationalConfig!) {
        const bindTable = !isCamelCase
          ? `${config.bindTable}List`
          : `${camelCaseString(config.bindTable!)}List`;
        const bindField = !isCamelCase ? config.bindField : camelCaseString(config.bindField!);
        if (config.type === 'computational' || config.type === 'money-chinese') {
          if (config.isMainForm) {
            //如果是主表字段 直接从formModel 取
            expressionStr += formModel[bindField!] || 0;
          } else {
            //如果是附表 从formModel 取出来 需要进行处理
            if (!formModel[bindTable]) return;
            if (config.computationalMethod) {
              const fieldArray = formModel[bindTable].map(
                (x: { [x: string]: any }) => Number(x[bindField!]) || 0,
              );
              switch (config.computationalMethod) {
                case 'sum':
                  expressionStr += `${sum(fieldArray)}`;
                  break;
                case 'mean':
                  expressionStr += `${mean(fieldArray)}`;
                  break;
                case 'min':
                  expressionStr += `${min(fieldArray)}`;
                  break;
                case 'max':
                  expressionStr += `${max(fieldArray)}`;
                  break;
              }
            } else {
              expressionStr +=
                (formModel[bindTable][props.index!] &&
                  formModel[bindTable][props.index!][bindField!]) ||
                0;
            }
          }
        } else {
          expressionStr += `${config.label!}`;
        }
      }

      if (props.computationalConfig!.length > 0) {
        try {
          valueRef.value =
            calculator(`(${expressionStr})`) === 'undefined'
              ? 0
              : Number(calculator(`(${expressionStr})`));
          emit('update:value', Number(formatter(valueRef.value.toString(), props.decimals)));
        } catch {
          console.error('计算式配置错误');
        }
      }
    },
    { deep: true, immediate: true },
  );

  const formatterVal = (value) => {
    return formatter(value, props.decimals);
  };

  /**
   * 点击之后隐藏
   */
  const handleClick = () => {
    visible.value = !visible.value;
    nextTick(() => {
      inputNumRef.value.focus();
    });
  };
  /**
   * 失去焦点 立马隐藏 显示中文
   */
  const handleBlur = () => {
    visible.value = !visible.value;
    emit('blur');
  };

  const handleChange = () => {
    emit('change');
  };
  const color = computed(() => {
    return props.style?.color;
  });
  const backgroundcolor = computed(() => {
    return props.style
      ? props.style['background-color'] || (props.disabled ? '#f5f5f5' : '#fff')
      : '#fff';
  });
  const border = computed(() => {
    return props.style?.border || '1px solid #d9d9d9';
  });
  const fontsize = computed(() => {
    return props.style ? props.style['font-size'] : '14px';
  });
  const fontstyle = computed(() => {
    return props.style ? props.style['font-style'] : 'normal';
  });
  const customwidth = computed(() => {
    return props.style?.width;
  });
  const height = computed(() => {
    return props.style?.height || '32px';
  });
  const textalign = computed(() => {
    return props.style ? props.style['text-align'] : 'left';
  });
</script>
<style scoped lang="less">
  .customStyle {
    width: v-bind(customwidth) !important;

    &.ant-input-group-wrapper {
      height: v-bind(height);
    }

    :deep(.ant-input) {
      height: v-bind(height);
      line-height: v-bind(height);
      background-color: v-bind(backgroundcolor);
      border: v-bind(border);
      font-size: v-bind(fontsize);
      font-style: v-bind(fontstyle);
      color: v-bind(color);
      text-align: v-bind(textalign);

      &[disabled] {
        color: v-bind(color);
      }
    }

    :deep(.ant-input-number) {
      background-color: v-bind(backgroundcolor);
      border: v-bind(border);
      font-size: v-bind(fontsize);
      font-style: v-bind(fontstyle);
      color: v-bind(color);
      text-align: v-bind(textalign);
      height: v-bind(height);
      line-height: v-bind(height);
    }
  }
</style>
