<template>
  <a-radio-group option-type="button"
                 v-bind="getBindValue"  :options="getOptions" v-model:value="modelValue"
  >
  </a-radio-group>
  <template v-if="tips">
    <p class="tips">{{tips}}</p>
  </template>
</template>

<script lang="ts">
import {computed, defineComponent, nextTick, PropType, ref, unref, watch} from 'vue';
  import { PropTypes, tuple } from '/nerv-lib/util/type';
import {HttpRequestConfig, useApi} from "/nerv-lib/use";
import {cloneDeep, get, isArray, isEqual, isFunction, isString, isUndefined} from "lodash-es";
type ChangeValue = string | number | undefined | string[] | number[];

  export default defineComponent({
    name: 'NsRadioGroupApi',
    props: {
      radioType: PropTypes.oneOf(tuple('radio', 'radioButton')).def('radioButton'),
      prefixCls: PropTypes.string,
      defaultValue: PropTypes.any,
      value: PropTypes.any,
      size: PropTypes.oneOf(tuple('large', 'default', 'small')).def('default'),
      // options: PropTypes.array,
      disabled: PropTypes.looseBool,
      name: PropTypes.string,
      buttonStyle: PropTypes.oneOf(tuple('outline', 'solid')).def('solid'),
      onChange: PropTypes.func,
      api: {
        type: [String, Object, Function] as PropType<string | Function | HttpRequestConfig>,
        required: true,
      },
      field: String,
      params: {
        type: Object,
        default: () => ({}),
      },
      resultField: {
        type: String,
        default: 'data.data',
      },
      firstOption: {
        type: Object,
      },
      numberToString: {
        type: Boolean,
        default: false,
      },
      paramsRequired: {
        type: [Boolean, Object],
        default: false,
      },
      labelField: {
        type: [String, Function],
        default: 'label',
      },
      valueField: {
        type: String,
        default: 'value',
      },
      autoSelectFirst: {
        type: Boolean,
        default: false,
      },
      //数据筛选函数
      filterData: {
        type: Function,
      },
      tips: {
        type: String,
        default: '',
      },
    },
    emits: ['change', 'validateChange'],
    // emits: ['update:value', 'change'],
    setup(props, { attrs, emit }) {
      let isLoading = false;
      const isLoad = ref(false);
      const options = ref([]);
      let isFirstLoad = !!props.api; // 是否第一次加载
      const changeValue = ref<any>(undefined);
      const filterFiledRef = ref<string | undefined>(undefined);


      const getBindValue = computed(() => {
        return {
          ...props,
          ...attrs,
        };
      });

      /**
       * 根据请求得到的data获取options
       */
      const getOptions = computed(() => {
        const { firstOption, labelField, valueField, numberToString } = props;
        const sourceOptions = [];
        firstOption && sourceOptions.push(firstOption);
        return unref(options).reduce((acc, next: Recordable) => {
          if (isString(next)) {
            //值是字符串类型
            const option = {
              label: next,
              value: next,
            };
            acc.push(option);
            return acc;
          } else {
            const value = get(next, valueField);
            const option = {
              ...next,
              label: isFunction(labelField) ? labelField(next) : get(next, labelField as string),
              value: numberToString ? `${value}` : value,
            };
            acc.push(option);
            return acc;
          }
          console.log(acc)
        }, sourceOptions);
      });
      /**
       * 获取数据
       */
      const fetch = () => {
        isLoading = true;
        const requestConfig: HttpRequestConfig = { method: 'get' };
        const {
          api,
          params: _params,
          resultField,
          filterData,
        } = props;
        const params: Recordable = cloneDeep(_params);
        const { httpRequest } = useApi();
        httpRequest({ api, params, requestConfig })
          .then((res: Recordable) => {
            emit('validateChange', { help: undefined });
            if (resultField) {
              let data = get(res, resultField) || [];
              // data = data.splice(Math.floor(Math.random() * 3), Math.floor(Math.random() * 5 + 5));
              if (isFunction(filterData)) {
                data = data.filter(filterData);
              }
              options.value = data;

            }
            isLoad.value = true;
            isLoading = false;
          })
          .catch((error: any) => {
            if (error?.response?.status === 403) {
              emit('validateChange', { help: '暂无权限', validateStatus: 'error' });
              nextTick(() => {
                //清空编辑初始值
                modelValue.value = undefined;
              });
            }
            options.value = [];
            isLoading = false;
          });
      };

      fetch();

      let lastParams: any = undefined;

      /**
       ** 绑定value
       */
      const modelValue = computed({
        set(value: ChangeValue) {
          if (isEqual(value, changeValue.value)) return;
          changeValue.value = value;
          triggerChange(value);
        },
        get() {
          return changeValue.value;
        },
      });
      /**
       * 传入值需要
       * 前提option已获取到数据
       */
      watch(
        () => props.value,
        () => {
          if (isLoad.value) {
            modelValue.value = props.value;
          }
        },
        {
          immediate: true,
        }
      );
      watch(
        () => getOptions.value,
        () => {
          const { value, autoSelectFirst } = props;
          // 首次加载如果有值则选中值
          if (isFirstLoad && !isUndefined(value)) {
            modelValue.value = value;
          }else if (!filterFiledRef.value) {
            if (autoSelectFirst) {
              modelValue.value = getOptions.value[0]?.value;
            }
          }
          isFirstLoad = false;
        }
      );
      /**
       * 重写change ant 初始化数据、删除数据时不触发change
       * @param value
       */
      function triggerChange(value: ChangeValue) {
        if (isUndefined(value)) {
          emit('change', value, undefined);
        } else if (isArray(value)) {
          const options: Record<string, any>[] = [];
          value.forEach((v) => {
            getOptions.value.forEach((option) => {
              if (option.value === v) {
                options.push(option);
              }
            });
          });
          emit('change', value, options);
        } else {
          let op = {};
          getOptions.value.forEach((option) => {
            if (option.value === value) {
              op = option;
            }
          });
          emit('change', value, op);
        }
      }
      /**
       ** 联动 immediate 为是否主动获取数据
       */
      watch(
        [() => props.params, () => props.api],
        async () => {
          const { params } = props;
          if (!isEqual(lastParams, params)) {
            if (props.immediate || true) {
              //todo 暂时全设为主动获取
              lastParams = cloneDeep(params);
              await fetch();
            }
            isLoad.value = false; // 设置成false 点击下拉才会触发
          }
        },
        { deep: true, immediate: props.immediate }
      );
      return {
        getBindValue,
        getOptions,
        modelValue,
      };
    },
  });
</script>
<style lang="less" scoped>
.tips {
  color: #7f7e7e;
  line-height: 20px;
  margin-bottom: 0;
}
</style>