<template>
  <template v-if="supportedRemoteSearch">
    <a-select
      style="width: 100%"
      :value="currentValue"
      :mode="multiple ? 'multiple' : '-'"
      :id="'form_item_' + formatFieldName(field.name)"
      :disabled="readOnly"
      :allowClear="field.clearable"
      :placeholder="placeholder"
      :filter-option="supportedFilterOption"
      :show-search="supportedRemoteSearch"
      @search="handleRemoteSearchValue"
      @change="handleChange"
    >
      <template v-if="remoteSearchLoading || remoteOptionsLoading" #notFoundContent>
        <a-spin size="small" />
      </template>
      <template
        v-else-if="supportedRemoteSearch || supportedRemoteOptions"
        #notFoundContent
      >
        {{
          remoteSearchErrorMsg
            ? remoteSearchErrorMsg
            : remoteOptionsErrorMsg
            ? remoteOptionsErrorMsg
            : notFoundContent
        }}
        <a-button
          v-if="remoteSearchErrorMsg || remoteOptionsErrorMsg"
          size="small"
          type="default"
          @click="handleRefresh"
        >
          刷新
        </a-button>
      </template>
      <a-select-option
        v-for="option in parseOptions(field.options)"
        :key="option.value"
        :value="option.value"
      >
        {{ readLabel(option.label) }}
        <template v-if="showValueTag">
          <span style="color: #999; font-size: 12px"> {{ option.value }} </span>
        </template>
        <template v-else>
          <span v-if="!!readTag(option.label)" style="color: #999; font-size: 12px">
            {{ readTag(option.label) }}
          </span>
        </template>
      </a-select-option>
    </a-select>
  </template>
  <template v-else>
    <a-select
      style="width: 100%"
      :value="currentValue"
      :mode="multiple ? 'multiple' : '-'"
      :id="'form_item_' + formatFieldName(field.name)"
      :disabled="readOnly"
      :allowClear="field.clearable"
      :placeholder="placeholder"
      :filter-option="supportedFilterOption"
      :show-search="false"
      @change="handleChange"
    >
      <template v-if="remoteSearchLoading || remoteOptionsLoading" #notFoundContent>
        <a-spin size="small" />
      </template>
      <template
        v-else-if="supportedRemoteSearch || supportedRemoteOptions"
        #notFoundContent
      >
        {{
          remoteSearchErrorMsg
            ? remoteSearchErrorMsg
            : remoteOptionsErrorMsg
            ? remoteOptionsErrorMsg
            : notFoundContent
        }}
        <a-button
          v-if="remoteSearchErrorMsg || remoteOptionsErrorMsg"
          size="small"
          type="default"
          @click="handleRefresh"
        >
          刷新
        </a-button>
      </template>
      <a-select-option
        v-for="option in parseOptions(field.options)"
        :key="option.value"
        :value="option.value"
      >
        {{ readLabel(option.label) }}
        <template v-if="showValueTag">
          <span style="color: #999; font-size: 12px"> {{ option.value }} </span>
        </template>
        <template v-else>
          <span v-if="!!readTag(option.label)" style="color: #999; font-size: 12px">
            {{ readTag(option.label) }}
          </span>
        </template>
      </a-select-option>
    </a-select>
  </template>
</template>

<script setup>
import { ref, computed, onMounted, watch } from "vue";
import { useVModel } from "@/iview/utils/useModel";
import { delayCall } from "@/iview/utils/delayCall";
import { callFunc } from "@/iview/utils/func";
import { toAny } from "@/iview/utils/toany";

const props = defineProps({
  field: {
    type: Object,
    required: true,
  },
  fieldPrefix: {
    type: String,
    default: "",
  },
  modelValue: {
    type: Object,
    required: true,
  },
  placeholder: {
    type: String,
    default: "请选择",
  },
  readOnly: {
    type: Boolean,
    default: false,
  },
  rawFormData: {
    type: Object,
  },
});

const emit = defineEmits(["update:modelValue"]);
const vModel = useVModel(props, "modelValue", emit);
const initValueFlag = ref(false);
const remoteOptionsData = ref([]);
const remoteOptionsLoading = ref(false);
const remoteOptionsErrorMsg = ref(null);

const remoteSearchValue = ref("");
const remoteSearchData = ref([]);
const remoteSearchLoading = ref(false);
const remoteSearchErrorMsg = ref(null);
const remoteSearchId = ref(0);

const handleChange = (value) => {
  if (multiple.value && maxSelectCount.value > 0 && value.length > maxSelectCount.value) {
    return;
  }
  vModel.value[formatFieldName(props.field.name)] = value;
};

const maxSelectCount = computed(() => {
  return props.field.maxSelectCount || 0;
});

const showValueTag = computed(() => {
  return !!props.field.showValueTag;
});

const notFoundContent = computed(() => {
  if (!supportedRemoteSearch.value) {
    return "暂无可选项";
  }
  return props.field.notFoundContent || !!remoteSearchValue.value
    ? "暂无可选项"
    : "输入关键字搜索";
});

const defaultValueList = computed(() => {
  return props.field.defaultValueList || [];
});

const forceInOptions = computed(() => {
  return props.field.forceInOptions === true;
});

const multiple = computed(() => {
  return props.field.multiple || false;
});

// 解析选项字符串或数组
const parseOptions = (options) => {
  if (remoteSearchData.value && remoteSearchData.value.length > 0) {
    return remoteSearchData.value;
  }
  if (remoteOptionsData.value && remoteOptionsData.value.length > 0) {
    return remoteOptionsData.value;
  }
  if (supportedRemoteSearch.value && currentValue.value) {
    return [
      {
        label: currentValue.value,
        value: currentValue.value,
      },
    ];
  }
  if (!options) return [];
  // 如果已经是数组，直接返回
  if (Array.isArray(options)) {
    return options;
  }
  // 如果是字符串，按换行符分割，再按|分割键值对
  if (typeof options === "string") {
    return options
      .split("\n")
      .filter((line) => line.trim() !== "")
      .map((line) => {
        const parts = line.split("|");
        return {
          label: parts[0]?.trim() || "",
          value: parts[1]?.trim() || parts[0]?.trim() || "",
        };
      });
  }
  return [];
};

const inOption = (value) => {
  let optionValues = parseOptions(props.field.options).map((item) => {
    return item.value;
  });
  return optionValues.includes(value);
};

const formatFieldName = (name) => {
  if (!props.fieldPrefix) {
    return name;
  }
  return props.fieldPrefix + "-" + name;
};

const readLabel = (value) => {
  return `${value}`.split("#")[0];
};

const readTag = (value) => {
  return `${value}`.split("#")[1];
};

const currentValue = computed(() => {
  let value = vModel.value[formatFieldName(props.field.name)];
  if (value === undefined || value === null) {
    return undefined;
  }
  if (!!value || inOption(value)) {
    return value;
  }
  return undefined;
});

const supportedRemoteSearch = computed(() => {
  return (
    !!props.field.remoteSearchMethod &&
    typeof props.field.remoteSearchMethod === "function"
  );
});

const supportedRemoteOptions = computed(() => {
  return (
    !!props.field.remoteOptionsMethod &&
    typeof props.field.remoteOptionsMethod === "function"
  );
});

const supportedFilterOption = computed(() => {
  return !!props.field.supportedFilterOption && !supportedRemoteSearch.value;
});

const handleRefresh = () => {
  if (!supportedRemoteSearch.value && !supportedRemoteOptions.value) {
    return;
  }
  if (supportedRemoteSearch.value && !!remoteSearchValue.value) {
    handleRemoteSearchValue(remoteSearchValue.value);
  }
  if (supportedRemoteOptions.value) {
    handleRemoteOptions();
  }
};

const handleRemoteOptions = () => {
  if (!supportedRemoteOptions.value) {
    return;
  }
  remoteOptionsLoading.value = true;
  remoteOptionsErrorMsg.value = null;
  Promise.resolve()
    .then(() => {
      let remoteOptionsMethod = props.field.remoteOptionsMethod;
      return callFunc([], [], remoteOptionsMethod, []);
    })
    .then((data) => {
      remoteOptionsData.value = data || [];
      remoteOptionsLoading.value = false;
    })
    .catch((err) => {
      remoteOptionsErrorMsg.value =
        (err && err.msg) || (err && err.message) || "连接服务器失败，请检查网络";
      remoteOptionsLoading.value = false;
    });
};

const handleRemoteSearchValue = delayCall((value) => {
  remoteSearchId.value += 1;
  remoteSearchValue.value = value;
  const currentRemoteSearchId = remoteSearchId.value;
  remoteSearchLoading.value = true;
  remoteSearchErrorMsg.value = null;
  remoteSearchData.value = [];
  Promise.resolve()
    .then(() => {
      let remoteSearchMethod = props.field.remoteSearchMethod;
      return callFunc(["value"], [value], remoteSearchMethod, []);
    })
    .then((data) => {
      if (currentRemoteSearchId !== remoteSearchId.value) {
        return;
      }
      remoteSearchData.value = data || [];
      remoteSearchLoading.value = false;
      remoteSearchValue.value = null;
    })
    .catch((err) => {
      remoteSearchErrorMsg.value =
        (err && err.msg) || (err && err.message) || "连接服务器失败，请检查网络";
      remoteSearchLoading.value = false;
    });
}, 300);

const readInitValue = () => {
  if (initValueFlag.value) {
    initValueFlag.value = false;
    return;
  }
  initValueFlag.value = true;
  let curValue = [];
  if (!!currentValue.value) {
    if (currentValue.value instanceof Array) {
      curValue = currentValue.value.filter((val) => !!val);
    } else if (typeof currentValue.value === "string") {
      curValue = [currentValue.value];
    }
  }
  let newValue = [];
  if (forceInOptions.value && !supportedRemoteSearch.value) {
    let inOptions = [];
    let options = parseOptions(props.field.options);
    for (let option of options) {
      curValue.forEach((val) => {
        if (option.value === val) {
          inOptions.push(option.value);
        }
      });
    }
    newValue = inOptions;
  } else {
    newValue = curValue;
  }
  if (newValue.length === 0) {
    newValue = defaultValueList.value || [];
  }
  if (newValue !== undefined && newValue !== null) {
    return multiple.value ? newValue : newValue[0];
  } else {
    return undefined;
  }
};

const checkValue = () => {
  let newValue = readInitValue();
  let curValue = currentValue.value;
  if (!!newValue && toAny(newValue, "") !== toAny(curValue, "")) {
    vModel.value[formatFieldName(props.field.name)] = newValue;
  }
};

onMounted(() => {
  checkValue();
  handleRemoteOptions();
});

watch(
  () => forceInOptions.value,
  () => {
    checkValue();
  }
);

watch(
  () => defaultValueList.value,
  () => {
    checkValue();
  }
);
</script>
