/* eslint-disable @typescript-eslint/no-non-null-assertion */
import type { DictItemApi } from '#/api/system/dict/dictData';

import { reactive } from 'vue';

import { defineStore } from 'pinia';

/**
 * antd使用 select和radio通用
 * 本质上是对DictItemApi.DictItem的拓展
 */
export interface DictOption extends DictItemApi.DictItem {
  disabled?: boolean;
  label: string;
  value: number | string;
  color?: string;
}

/**
 * 将字典数据转为Options
 * @param data 字典数据
 * @param formatNumber 是否需要将value格式化为number类型
 * @returns options
 */
export function dictToOptions(
  data: DictItemApi.DictItem[],
  formatNumber = false,
): DictOption[] {
  return data.map((item) => ({
    ...item,
    label: item.dictLabel,
    value: formatNumber ? Number(item.dictValue) : item.dictValue,
  }));
}

export const useDictStore = defineStore('app-dict', () => {
  /**
   * select radio checkbox等使用 只能为固定格式{label, value}
   */
  const dictOptionsMap = reactive(new Map<string, DictOption[]>());
  /**
   * 添加一个字典请求状态的缓存
   *
   * 主要解决多次请求重复api的问题(不能用abortController 会导致除了第一个其他的获取的全为空)
   * 比如在一个页面 index表单 modal drawer总共会请求三次 但是获取的都是一样的数据
   * 相当于加锁 保证只有第一次请求的结果能拿到
   */
  const dictRequestCache = reactive(
    new Map<string, Promise<DictItemApi.DictItem[] | void>>(),
  );

  function getDictOptions(dictName: string): DictOption[] {
    if (!dictName) return [];
    // 没有key 添加一个空数组
    if (!dictOptionsMap.has(dictName)) {
      dictOptionsMap.set(dictName, []);
    }
    // 这里拿到的就不可能为空了
    return dictOptionsMap.get(dictName)!;
  }

  function resetCache() {
    dictRequestCache.clear();
    dictOptionsMap.clear();
    /**
     * 不需要清空dictRequestCache 每次请求成功/失败都清空key
     */
  }

  /**
   * 核心逻辑
   *
   * 不能直接粗暴使用set 会导致之前return的空数组跟现在的数组指向不是同一个地址  数据也就为空了
   *
   * 判断是否已经存在key 并且数组长度为0 说明该次要处理的数据是return的空数组 直接push(不修改指向)
   * 否则 直接set
   *
   */
  function setDictInfo(
    dictName: string,
    dictValue: DictItemApi.DictItem[],
    formatNumber = false,
  ) {
    if (
      dictOptionsMap.has(dictName) &&
      dictOptionsMap.get(dictName)?.length === 0
    ) {
      dictOptionsMap
        .get(dictName)
        ?.push(...dictToOptions(dictValue, formatNumber));
    } else {
      dictOptionsMap.set(dictName, dictToOptions(dictValue, formatNumber));
    }
  }

  function $reset() {
    /**
     * doNothing
     */
  }

  return {
    $reset,
    dictOptionsMap,
    dictRequestCache,
    getDictOptions,
    resetCache,
    setDictInfo,
  };
});
