<script setup lang="ts">
import { useDebounceFn } from "@vueuse/core";
import { ref, onMounted, reactive, onUnmounted, watch } from "vue";
import { httpBusinessList, httpSupplierList } from "/@/api/user";
import { useResponseHandle } from "/@/hooks/core/useAsync";
import { useCompany } from "/@/hooks/core/useCompany";
import { useUserInfo } from "/@/hooks/core/useUser";

const emit = defineEmits(["change", "update:code"]);

const props = withDefaults(
  defineProps<{
    noAll?: boolean;
    noSet?: boolean;
    code?: string;
    isSupplier?: boolean;
    placeholder?: string;
  }>(),
  {
    code: ""
  }
);

const { setCurrentCompany } = useCompany();
const responseHandle = useResponseHandle();

const { userLevel } = useUserInfo();

const code = ref(props.code);
const selectRef = ref(null);
const list = ref<any[]>([]);

const state = reactive({
  loading: false,
  noMore: false,
  name: "",
  count: 0,
  page: 1
});

let scrollWrapper: HTMLDivElement | null = null;

const debouceScroll = useDebounceFn(handleScroll, 500);

function convertList(list) {
  const isSupplier = userLevel.value === "3" || props.isSupplier;

  if (isSupplier) return list;

  return list.map(item => ({
    ...item,
    code: item.companyNo,
    name: item.company_name
  }));
}

async function requesetSupplierAll(name: string, companyNo: string) {
  state.name = name;
  state.page = 1;
  state.noMore = false;
  const isSupplier = userLevel.value === "3" || props.isSupplier;
  const api =
    isSupplier || props.isSupplier ? httpSupplierList : httpBusinessList;
  const { data, message, code } = await api({
    [isSupplier ? "name" : "company_name"]: state.name,
    [isSupplier ? "code" : "companyNo"]: companyNo,
    page: state.page
  });

  responseHandle({
    code,
    message,
    handler: () => {
      list.value = convertList(data.list);
      state.count = data.count;
      state.loading = false;
      const maxPage = Math.ceil(state.count / 10);
      state.noMore = maxPage <= 1;
    }
  });
}

function handleChange(value) {
  const item = list.value.find(({ code }) => code === value);
  if (!props.noSet) {
    setCurrentCompany(item);
  }
  emit("change", item);
}

async function handleScroll() {
  const height = scrollWrapper.clientHeight;
  const scrollTop = scrollWrapper.scrollTop;
  const scrollHeight = scrollWrapper.scrollHeight;

  if (height + scrollTop >= scrollHeight && !state.noMore) {
    state.page++;
    state.loading = true;

    const api =
      userLevel.value === "3" || props.isSupplier
        ? httpSupplierList
        : httpBusinessList;

    const { data, message, code } = await api({
      name: state.name,
      page: state.page,
      noRela: true
    });
    const pushCompany = (_list: any[]) => {
      list.value = [...list.value, ...convertList(_list)];
    };

    responseHandle({
      code,
      message,
      handler: () => {
        state.count = data.count;
        const maxPage = Math.ceil(state.count / 10);

        if (state.page > maxPage) {
          state.noMore = true;
          state.loading = false;
          return;
        }

        pushCompany(data.list);
      }
    });
  }
}

onMounted(() => {
  setTimeout(() => {
    const superItem = document.querySelector(".super-item");
    if (!superItem) return;
    scrollWrapper = superItem.parentElement?.parentElement as HTMLDivElement;
    if (scrollWrapper) {
      scrollWrapper.addEventListener("scroll", debouceScroll, false);
    }
  }, 1000);
});

onUnmounted(() => {
  state.loading = false;
  state.noMore = false;
  state.name = "";
  state.page = 1;

  if (scrollWrapper) {
    scrollWrapper.removeEventListener("scroll", debouceScroll);
  }
});

watch(
  () => userLevel.value,
  level => {
    if (level !== "") {
      state.loading = false;
      state.noMore = false;
      state.name = "";
      state.page = 1;
      list.value = [];
      requesetSupplierAll(undefined, props.code);
    }
  }
);

const getLabel = company => {
  const { code, name } = company;
  return code + " / " + name;
};

requesetSupplierAll(undefined, props.code);

defineExpose({
  selectAll: () => (code.value = "")
});
</script>

<template>
  <ElSelect
    filterable
    remote
    v-model="code"
    :remote-method="requesetSupplierAll"
    @change="handleChange"
    style="width: 450px"
    :placeholder="placeholder"
    ref="selectRef"
  >
    <ElOption
      v-if="!noAll"
      :label="userLevel === '3' ? '所有供应商公司' : '所有业务公司'"
      :value="''"
    />
    <ElOption
      class="super-item"
      v-for="c in list"
      :key="c.code"
      :value="c.code"
      :label="getLabel(c)"
    />

    <p class="super-loading" v-if="state.loading">
      <IconifyIconOffline class="animate-spin" icon="Loading" />
      加载中
    </p>

    <p class="super-no-more" v-if="state.noMore">没有更多数据了...</p>
  </ElSelect>
</template>

<style lang="scss" scoped>
.super-no-more {
  text-align: center;
  color: #999;
  font-size: 14px;
  line-height: 38px;
}

.super-loading {
  display: flex;
  font-size: 14px;
  justify-content: center;
  align-items: center;
  color: #999;
  gap: 10px;
  line-height: 38px;
}
</style>
