import { computed, toValue } from 'vue';
import type { ComputedRef, MaybeRefOrGetter, Ref } from 'vue';
import { useDictStore } from '@/store/modules/dict';

type DictCode = string | Ref<string> | ComputedRef<string>;
type DictValue = string | number | null | undefined;
type DictValueList = Array<DictValue> | null | undefined;
type DictFilterOptions = {
  onlyEnabled?: boolean;
};
type DictLabelOptions = string | (DictFilterOptions & { fallback?: string });
type DictLabelsOptions = string | (DictFilterOptions & { fallback?: string; separator?: string });

function normalizeLabelOptions(options?: DictLabelOptions) {
  if (typeof options === 'string') {
    return {
      fallback: options,
      onlyEnabled: false
    };
  }

  return {
    fallback: options?.fallback ?? '--',
    onlyEnabled: options?.onlyEnabled ?? false
  };
}

function normalizeLabelsOptions(options?: DictLabelsOptions) {
  if (typeof options === 'string') {
    return {
      fallback: options,
      separator: ' / ',
      onlyEnabled: false
    };
  }

  return {
    fallback: options?.fallback ?? '--',
    separator: options?.separator ?? ' / ',
    onlyEnabled: options?.onlyEnabled ?? false
  };
}

export function useDict(dictCode: DictCode | MaybeRefOrGetter<string>) {
  const dictStore = useDictStore();

  const currentDictCode = computed(() => toValue(dictCode));

  const dictData = computed(() => dictStore.getDictData(currentDictCode.value));
  const enabledDictData = computed(() => dictStore.getDictData(currentDictCode.value, true));
  const dictOptions = computed(() => dictStore.getDictOptions(currentDictCode.value));
  const dictMap = computed(() => new Map(dictData.value.map(item => [item.value, item])));
  const enabledDictMap = computed(() => new Map(enabledDictData.value.map(item => [item.value, item])));

  function getItem(value?: DictValue, options: DictFilterOptions = {}) {
    return dictStore.getDictItem(currentDictCode.value, value, options);
  }

  function getLabel(value?: DictValue, options?: DictLabelOptions) {
    const normalizedOptions = normalizeLabelOptions(options);

    return dictStore.getDictLabel(currentDictCode.value, value, normalizedOptions);
  }

  function getLabels(values?: DictValueList, options?: DictLabelsOptions) {
    const normalizedOptions = normalizeLabelsOptions(options);

    return dictStore.getDictLabels(currentDictCode.value, values, normalizedOptions);
  }

  function hasValue(value?: DictValue, options: DictFilterOptions = {}) {
    return dictStore.hasDictValue(currentDictCode.value, value, options);
  }

  return {
    dictData,
    enabledDictData,
    dictOptions,
    dictMap,
    enabledDictMap,
    getItem,
    getLabel,
    getLabels,
    hasValue
  };
}
