<!-- 物料选择 -->
<template>
  <a-select
    v-model:value="selectedValue"
    showSearch
    :placeholder="placeholder"
    :loading="loading"
    :allowClear="true"
    :filterOption="filterOption"
    :notFoundContent="notFoundContent"
    :mode="multiple ? 'multiple' : 'default'"
    @change="handleChange"
    @search="handleSearch"
    @focus="handleFocus"
    @popup-scroll="handlePopupScroll"
    :getPopupContainer="getParentContainer"
    v-bind="attrs"
  >
    <template #notFoundContent>

    </template>
    <a-select-option v-for="option in Options" :key="option.id" :value="getOptionValue(option)">
      {{ getOptionLabel(option) }}
    </a-select-option>
  </a-select>
</template>

<script lang="ts">
  import { defineComponent, ref, watch, computed, onMounted } from 'vue';
  import { useAttrs } from '/@/hooks/core/useAttrs';
  import { propTypes } from '/@/utils/propTypes';
  import { defHttp } from '/@/utils/http/axios';
  import { queryById } from '@/views/base/item/Item.api';
  import { setPopContainer } from '/@/utils';
  import { debounce } from 'lodash-es';

  // 物料数据接口
  interface Item {
    id: string;
    itemCode: string;
    itemName: string;
  }

  //响应数据接口
  interface ResponseData {
    records: Item[];
    total: number;
    size: number;
    current: number;
    page: number;
  }

  export default defineComponent({
    name: 'ItemSelect',
    inheritAttrs: false,
    props: {
      // 选中值，支持v-model
      value: propTypes.oneOfType([propTypes.string, propTypes.array, propTypes.object]),
      // 占位符
      placeholder: propTypes.string.def('请选择物料'),
      // 是否多选
      multiple: propTypes.bool.def(false),
      // 是否异步加载数据
      async: propTypes.bool.def(true),
      // 分页大小
      pageSize: propTypes.number.def(10),
      // 弹出层容器
      popContainer: propTypes.string,
      // 自定义弹出层容器函数
      getPopupContainer: {
        type: Function,
        default: (node: HTMLElement) => node?.parentNode,
      },
      // 是否立即触发change事件
      immediateChange: propTypes.bool.def(false),
      // 返回值类型: 'id'(默认) | 'object' | 其他字段名
      returnValue: propTypes.string.def('id'),
      //默认启用
      izActive: propTypes.number.def(1),
      //默认未删除
      delFlag: propTypes.number.def(0),
    },
    emits: ['change', 'update:value', 'optionsLoaded'],
    setup(props, { emit }) {
      const Options = ref<Item[]>([]);
      const loading = ref<boolean>(false);
      const allItems = ref<Item[]>([]);
      const attrs = useAttrs({ excludeDefaultKeys: false });

      // 分页相关
      const pageNo = ref(1);
      const isHasData = ref(true);
      const scrollLoading = ref(false);
      const searchKeyword = ref('');

      // 选中值
      const selectedValue = ref<string | string[] | undefined>(undefined);

      // 未找到内容
      const notFoundContent = computed(() => {
        return loading.value ? undefined : '暂无数据';
      });

      /**
       * 获取选项显示文本 - 始终显示完整格式
       */
      function getOptionLabel(option: Item) {
        return `${option.itemCode} - ${option.itemName}`;
      }

      /**
       * 获取选项值 - 根据returnValue确定实际存储的值
       */
      function getOptionValue(option: Item) {
        if (props.returnValue === 'object') {
          return option.id; // 对于object类型，仍然使用id作为选项值，但在change事件中返回完整对象
        } else if (props.returnValue === 'id') {
          return option.id;
        } else {
          return option[props.returnValue as keyof Item] as string;
        }
      }

      /**
       * 获取弹出层容器
       */
      function getParentContainer(node: HTMLElement) {
        if (props.popContainer) {
          return setPopContainer(node, props.popContainer);
        } else {
          if (typeof props.getPopupContainer === 'function') {
            return props.getPopupContainer(node);
          } else {
            return node?.parentNode;
          }
        }
      }

      /**
       * 过滤选项 - 禁用前端过滤，使用后端搜索
       */
      function filterOption(_input: string, _option: any) {
        return true; // 禁用前端过滤，完全依赖后端搜索
      }

      /**
       * 确保物料唯一性的辅助函数
       */
      function ensureUnique(items: Item[], newItem: Item): Item[] {
        // 如果已经存在相同id的物料，先移除旧的再添加新的
        const filtered = items.filter(item => item.id !== newItem.id);
        return [newItem, ...filtered];
      }

      /**
       * 获取物料数据
       */
      const queryData = async (page = 1, keyword = '', isSearch = false) => {
        try {
          loading.value = true;

          const res = await defHttp.get<ResponseData>({
            url: '/base/item/list',
            params: {
              pageSize: props.pageSize,
              pageNo: page,
              keyword: keyword,
              izActive: props.izActive,
              delFlag: props.delFlag,
            },
          });

          const records = res.records || [];

          if (page === 1 || isSearch) {
            // 第一页或搜索时，重置数据
            allItems.value = records;
            Options.value = records;
          } else {
            // 滚动加载时，追加数据（确保不重复）
            const newRecords = records.filter(record =>
              !allItems.value.some(item => item.id === record.id)
            );
            allItems.value = [...allItems.value, ...newRecords];
            Options.value = [...Options.value, ...newRecords];
          }

          // 修正分页判断逻辑
          isHasData.value = records.length >= props.pageSize;

          emit('optionsLoaded', allItems.value);
        } catch (error) {
          if (page === 1) {
            allItems.value = [];
            Options.value = [];
          }
        } finally {
          loading.value = false;
          scrollLoading.value = false;
        }
      };

      async function queryDataById(value: string) {
        try {
          const res = await queryById({ id: value });
          if (res) {
            // 将查询到的单个物料信息添加到列表中，确保唯一性
            const item = Array.isArray(res) ? res[0] : res;
            if (item) {
              // 使用ensureUnique确保物料不重复
              allItems.value = ensureUnique(allItems.value, item);
              Options.value = ensureUnique(Options.value, item);
            }
            return item;
          }
        } catch (error) {
          console.error('查询物料失败:', error);
        }
        return null;
      }

      /**
       * 根据选项值找到对应的选项对象
       */
      function findOptionByValue(value: string): Item | undefined {
        if (props.returnValue === 'object' || props.returnValue === 'id') {
          return allItems.value.find((item) => item.id === value);
        } else {
          return allItems.value.find((item) => item[props.returnValue as keyof Item] === value);
        }
      }

      /**
       * 获取需要返回的值
       */
      function getReturnValue(value: string | string[]) {
        if (!value) {
          return props.multiple ? [] : undefined;
        }

        // 如果返回整个对象
        if (props.returnValue === 'object') {
          if (Array.isArray(value)) {
            return value.map((v) => findOptionByValue(v)).filter(Boolean);
          } else {
            return findOptionByValue(value);
          }
        }
        // 如果返回ID（默认情况）
        else if (props.returnValue === 'id') {
          return value;
        }
        // 如果返回对象中的某个字段
        else {
          if (Array.isArray(value)) {
            return value.map((v) => {
              const option = findOptionByValue(v);
              return option ? option[props.returnValue as keyof Item] : v;
            });
          } else {
            const option = findOptionByValue(value);
            return option ? option[props.returnValue as keyof Item] : value;
          }
        }
      }

      /**
       * 搜索处理（防抖）
       */
      const handleSearch = debounce(function (value: string) {
        searchKeyword.value = value;
        pageNo.value = 1;
        isHasData.value = true;

        // 直接调用API进行搜索
        queryData(1, value, true);
      }, 300);

      /**
       * 处理焦点事件
       */
      function handleFocus() {
        // 如果还没有数据，加载数据
        if (allItems.value.length === 0 && props.async) {
          pageNo.value = 1;
          isHasData.value = true;
          queryData(1, '');
        }
        attrs.onFocus?.();
      }

      /**
       * 处理值变化
       */
      function handleChange(value: string | string[]) {
        selectedValue.value = value;

        // 根据配置返回相应的值
        const returnValue = getReturnValue(value);
        emit('update:value', returnValue);
        emit('change', returnValue);
      }

      /**
       * 滚动加载处理
       */
      function handlePopupScroll(e: Event) {
        const target = e.target as HTMLElement;
        const { scrollTop, scrollHeight, clientHeight } = target;

        if (!scrollLoading.value && isHasData.value && scrollTop + clientHeight >= scrollHeight - 10) {
          scrollLoading.value = true;
          pageNo.value++;

          queryData(pageNo.value, searchKeyword.value)
            .finally(() => {
              scrollLoading.value = false;
            })
            .catch(() => {
              pageNo.value--;
            });
        }
      }

      /**
       * 根据选中值初始化显示文本
       */
      const initSelectValue = async () => {
        if (!props.value) {
          selectedValue.value = props.multiple ? [] : undefined;
          return;
        }

        // 如果是异步模式且还没有加载数据，则先加载数据
        if (props.async && allItems.value.length === 0) {
          await queryData();
        }

        // 根据不同的returnValue设置选中的值
        let valueIds: string[] = [];

        if (props.returnValue === 'object') {
          // 如果返回的是对象，value可能是对象或对象数组
          if (Array.isArray(props.value)) {
            valueIds = props.value.map((item: any) => item.id);
            selectedValue.value = valueIds;
          } else {
            valueIds = [(props.value as any).id];
            selectedValue.value = valueIds[0];
          }
        } else if (props.returnValue === 'id') {
          if (Array.isArray(props.value)) {
            valueIds = props.value as string[];
            selectedValue.value = valueIds;
          } else {
            valueIds = [props.value as string];
            selectedValue.value = valueIds[0];
          }
        } else {
          // 对于其他字段类型，直接使用传入的值
          selectedValue.value = props.value as string | string[];
          // 这里需要根据字段值查找对应的ID
          if (Array.isArray(props.value)) {
            valueIds = props.value.map((v) => {
              const option = allItems.value.find((item) => item[props.returnValue as keyof Item] === v);
              return option ? option.id : v;
            });
          } else {
            const option = allItems.value.find((item) => item[props.returnValue as keyof Item] === props.value);
            valueIds = option ? [option.id] : [props.value as string];
          }
        }

        // 检查是否有值不在当前列表中，如果有则查询
        const missingIds = valueIds.filter((id) => !allItems.value.some((item) => item.id === id));
        if (missingIds.length > 0) {
          // 对每个不在列表中的ID进行查询
          const queryPromises = missingIds.map((id) => queryDataById(id));
          await Promise.all(queryPromises);
        }
      };

      // 监听value变化
      watch(
        () => props.value,
        () => {
          initSelectValue();
        },
        { immediate: true }
      );

      // 组件挂载时初始化
      onMounted(() => {
        if (!props.async) {
          queryData();
        }
      });

      return {
        attrs,
        Options,
        loading,
        selectedValue,
        notFoundContent,
        getParentContainer,
        filterOption,
        handleChange,
        handleSearch,
        handleFocus,
        getOptionLabel,
        getOptionValue,
        handlePopupScroll,
      };
    },
  });
</script>

<style lang="less" scoped></style>
