<script setup lang="ts">
import type { CheckboxValueType } from 'ant-design-vue/es/checkbox/interface';

import type { ApiConfig } from '../types';

import type { BasicOptionResult } from '#/api/model';

import { computed, type PropType, ref, unref, watch, watchEffect } from 'vue';

import { isFunction } from '@vben/utils';

import { useVModel } from '@vueuse/core';
import { CheckboxGroup, Spin } from 'ant-design-vue';

import { get, omit } from '#/utils';

import { createApiFunction } from '../helper';

const props = defineProps({
  value: {
    type: [Array] as PropType<CheckboxValueType[]>,
    default: undefined,
  },
  numberToString: {
    type: Boolean,
    default: false,
  },
  api: {
    type: Object as PropType<ApiConfig>,
    default: () => ({
      type: 'none',
      method: 'get',
      params: {},
      result: '',
      url: null,
    }),
  },
  fieldNames: {
    type: Object as PropType<{ label: string; options: any; value: string }>,
    default: () => ({ label: 'label', value: 'value', options: null }),
  },
  immediate: {
    type: Boolean,
    default: true,
  },
});
const emit = defineEmits(['update:value', 'optionsChange']);
const modelValue = useVModel(props, 'value', emit, {
  defaultValue: props.value,
  passive: true,
});
const options = ref<BasicOptionResult[]>([]);
const loading = ref(false);
const isFirstLoad = ref(true);
const getOptions = computed(() => {
  const { fieldNames, numberToString } = props;
  const res: BasicOptionResult[] = [];
  unref(options).forEach((item: any) => {
    const value = item[fieldNames.value];
    res.push({
      ...omit(item, [fieldNames.label, fieldNames.value]),
      label: item[fieldNames.label],
      value: numberToString ? `${value}` : value,
      disabled: item.disabled || false,
    });
  });
  return res;
});

const emitChange = () => {
  emit('optionsChange', unref(getOptions));
};

const fetch = async () => {
  const api = createApiFunction({ ...props.api });
  if (!api || !isFunction(api)) return;
  try {
    loading.value = true;
    const res = await api(props.api.params);
    if (Array.isArray(res)) {
      options.value = res;
    } else {
      options.value = props.api.result ? get(res, props.api.result) : [];
    }
    emitChange();
  } catch (error) {
    console.warn(error);
  } finally {
    loading.value = false;
  }
};
watchEffect(() => {
  props.immediate && fetch();
});

watch(
  () => props.api.params,
  () => {
    !unref(isFirstLoad) && fetch();
  },
  { deep: true },
);
</script>

<template>
  <Spin :spinning="loading" style="margin-left: 20px">
    <CheckboxGroup
      v-bind="$attrs"
      v-model:value="modelValue"
      :options="getOptions"
      class="w-full"
    >
      <template v-for="item in Object.keys($slots)" #[item]="data">
        <slot :name="item" v-bind="data || {}"></slot>
      </template>
    </CheckboxGroup>
  </Spin>
</template>
