<!-- 选择下拉框 -->
<template>
  <a-select
    :allow-clear="true"
    :show-search="true"
    optionFilterProp="label"
    :options="data"
    :value="innerValue"
    :placeholder="placeholder"
    @update:value="updateValue"
    :style="`width: ${width}px`"
    @change="change"
    @blur="onBlur"
  />
</template>

<script lang="ts" setup>
  import { ref, watch } from 'vue';
  import {listDictData} from "@/api/system/dict-data";

  const data = ref<any[]>([]);
  const innerValue = ref<string | number | undefined>(undefined);

  const emit = defineEmits<{
    (e: 'update:value', value: string | number | undefined): void;
    (e: 'index', index: number): void;
    (e: 'blur'): void;
    (e: 'done', item: any): void;
  }>();

  const props = withDefaults(
    defineProps<{
      value?: string | number;
      placeholder?: string;
      dictCode?: string;
      showSearch?: string;
      allowClear?: boolean;
      width?: number;
      index?: number;
      valueType?: 'id' | 'code' | 'name';
    }>(),
    {
      placeholder: '请选择服务器厂商',
      valueType: 'id'
    }
  );

  innerValue.value = props.value as any;

  const normalizeInnerValue = () => {
    const raw = props.value;
    if (raw === undefined || raw === null || raw === '') {
      innerValue.value = raw as any;
      return;
    }
    const rawStr = String(raw);
    const matchById = data.value.find((d) => String(d.dictDataId) === rawStr);
    const matchByCode = data.value.find((d) => String(d.dictDataCode) === rawStr);
    const matchByName = data.value.find((d) => String(d.dictDataName) === rawStr);

    const setInnerValue = (next: string | number) => {
      innerValue.value = next;
    };
    const emitIfChanged = (next: string | number) => {
      if (String(raw) !== String(next)) {
        emit('update:value', next);
        emit('done', data.value.find((d) => String(d.value) === String(next)));
      }
    };

    if (props.valueType === 'name') {
      const next = matchByName?.dictDataName ?? matchById?.dictDataName ?? matchByCode?.dictDataName;
      if (next !== undefined) {
        setInnerValue(next);
        emitIfChanged(next);
        return;
      }
    } else if (props.valueType === 'code') {
      const next = matchByCode?.dictDataCode ?? matchById?.dictDataCode ?? matchByName?.dictDataCode;
      if (next !== undefined) {
        setInnerValue(next);
        emitIfChanged(next);
        return;
      }
    } else if (props.valueType === 'id') {
      const next =
        matchById?.dictDataId ??
        matchByCode?.dictDataId ??
        matchByName?.dictDataId ??
        raw;
      setInnerValue(next);
      return;
    }

    innerValue.value = raw as any;
  };

  // 字典数据
  listDictData({dictCode: props.dictCode}).then(res => {
    data.value = res.map(d => {
      const optionValue =
        props.valueType === 'name'
          ? d.dictDataName
          : props.valueType === 'code'
            ? d.dictDataCode
            : d.dictDataId;
      return {
        dictDataId: d.dictDataId,
        dictDataCode: d.dictDataCode,
        dictDataName: d.dictDataName,
        key: d.dictDataCode,
        value: optionValue,
        label: d.dictDataName,
        comments: d.comments
      };
    });
    normalizeInnerValue();
  });

  watch(
    () => props.value,
    () => {
      normalizeInnerValue();
    }
  );

  /* 更新选中数据 */
  const updateValue = (value: string | number) => {
    innerValue.value = value;
    emit('update:value', value);
    emit('index', Number(props.index));
    emit('done', data.value.find(d => String(d.value) === String(value)))
  };

  /* 失去焦点 */
  const onBlur = () => {
    emit('blur');
  };

  const change = (e, item) => {
    emit('done', item);
  };
</script>
