import dayjs from 'dayjs';
import type { DataNode } from 'ant-design-vue/es/vc-tree-select/interface';
import { add, subtract, multiply, divide, bignumber, type BigNumber, format } from 'mathjs';
/**
 * @description 处理首字母大写 abc => Abc
 * @param str
 */
export const changeStr = (str: string) => {
  return str.charAt(0).toUpperCase() + str.slice(1);
};

/**
 * @description 随机生成颜色
 * @param {string} type
 * @return {string}
 */
export const randomColor = (type: 'rgb' | 'hex' | 'hsl'): string => {
  switch (type) {
    case 'rgb':
      return window.crypto.getRandomValues(new Uint8Array(3)).toString();
    case 'hex':
      return `#${Math.floor(Math.random() * 0xffffff)
        .toString(16)
        .padStart(6, `${Math.random() * 10}`)}`;
    case 'hsl':
      // 在25-95%范围内具有饱和度，在85-95%范围内具有亮度
      return [360 * Math.random(), `${100 * Math.random()}%`, `${100 * Math.random()}%`].toString();
  }
};

/**
 * 复制文本
 * @param text
 */
export const copyText = (text: string) => {
  const copyInput = document.createElement('input'); //创建一个input框获取需要复制的文本内容
  copyInput.value = text;
  document.body.appendChild(copyInput);
  copyInput.select();
  document.execCommand('copy');
  copyInput.remove();
};

/**
 * @description 判断字符串是否是base64
 * @param {string} str
 */
export const isBase64 = (str: string): boolean => {
  if (str === '' || str.trim() === '') {
    return false;
  }
  try {
    return btoa(atob(str)) == str;
  } catch (err) {
    return false;
  }
};
// 对象转JSON
export const toJSON = (obj) => {
  return JSON.stringify(obj, (_, value) => {
    switch (true) {
      case typeof value === 'undefined':
        return 'undefined';
      case typeof value === 'symbol':
        return value.toString();
      case typeof value === 'function':
        return value.toString();
      default:
        break;
    }
    return value;
  });
};

/***
 * @description 是否是生产环境
 */
export const IS_PROD = import.meta.env.PROD;
export const IS_DEV = import.meta.env.DEV;

/***
 * @description 格式化日期
 * @param time
 */
export const formatDate = (time) => dayjs(time).format('YYYY-MM-DD HH:mm:ss');

/**
 *  @description 将一维数组转成树形结构数据
 * @param items
 * @param id
 * @param link
 */
export const generateTree = (items, id = 0, link = 'parent') => {
  return items
    .filter((item) => item[link] == id)
    .map((item) => ({
      ...item,
      slots: { title: 'name' },
      children: generateTree(items, item.departmentid),
    }));
};

/***
 * @description 原生加密明文
 * @param {string} plaintext
 */
// const encryption = (plaintext: string) =>
//   isBase64(plaintext) ? plaintext : window.btoa(window.encodeURIComponent(plaintext));

/**
 * @description 原生解密
 * @param {string} ciphertext
 */
// const decryption = (ciphertext: string) =>
//   isBase64(ciphertext) ? window.decodeURIComponent(window.atob(ciphertext)) : ciphertext;

// const viewsModules = import.meta.glob('../views/**/*.vue');

// /**
//  *
//  * @param {string} viewPath 页面的路径 `@/view/${viewPath}`
//  * @param {string} viewFileName  页面文件 默认 index.vue
//  */
// export const getAsyncPage = (viewPath: string, viewFileName = 'index') => {
//   if (viewPath.endsWith('.vue')) {
//     const p = `../views/${viewPath}`;
//     const pathKey = Object.keys(viewsModules).find((key) => key === p)!;
//     // console.log('viewsModules[pathKey]', viewsModules[pathKey]);
//     return viewsModules[pathKey];
//   } else {
//     const p = `../views/${viewPath}/${viewFileName}.vue`;
//     const pathKey = Object.keys(viewsModules).find((key) => key === p)!;
//     // console.log('viewsModules[pathKey]', viewsModules[pathKey]);
//     return viewsModules[pathKey];
//     // return () => import(/* @vite-ignore */ `../views/${viewPath}/${viewFileName}.vue`);
//   }
// };

/**
 * / _ - 转换成驼峰并将view替换成空字符串
 * @param {*} name name
 */
export const toHump = (name) => {
  return name
    .replace(/[-/_](\w)/g, (_, letter) => {
      return letter.toUpperCase();
    })
    .replace('views', '');
};

/** 模拟异步请求，实用性不高，主要用于demo模拟请求 */
export const waitTime = <T>(time = 100, data: any = true): Promise<T> => {
  const { promise, resolve } = Promise.withResolvers<T>();
  setTimeout(() => {
    resolve(data);
  }, time);
  return promise;
};

export function findPath<T extends Key>(
  tree: Recordable[],
  targetId: T,
  field = 'id',
  currentPath: T[] = [],
): T[] | null {
  // 遍历树中的每个节点
  for (const node of tree) {
    // 将当前节点的 ID 添加到路径中
    const path = [...currentPath, node[field]];

    // 如果找到目标节点，返回路径
    if (node.id === targetId) {
      return path;
    }

    // 如果当前节点有子节点，则递归查找子节点
    if (node.children && node.children.length > 0) {
      const childPath = findPath(node.children, targetId, field, path);
      if (childPath) {
        return childPath;
      }
    }
  }

  // 没有找到目标节点，返回 null
  return null;
}

export const str2tree = (str: string, treeData: DataNode[] = [], separator = ':') => {
  return str.split(separator).reduce((prev, curr, currentIndex, arr) => {
    const path = arr.slice(0, currentIndex + 1).join(':');
    const index = prev.findIndex((item) => item?.path === path);
    if (index !== -1) {
      return prev[index].children;
    } else {
      const item: DataNode = {
        // key: curr,
        path,
        value: curr,
        label: curr,
        children: [],
      };
      prev.push(item);
      return item.children!;
    }
  }, treeData);
};

type CalclateOption = 'add' | 'subtract' | 'multiply' | 'divide';
export function calcNumber(
  firstNumber: number,
  secondNumber: number,
  option: CalclateOption,
  precision: number = 14,
): number {
  let result: BigNumber;
  switch (option) {
    case 'add':
      // 添加精度保留2位小数     add(bignumber(firstNumber), bignumber(secondNumber)).toNumber();
      result = add(bignumber(firstNumber), bignumber(secondNumber));
      break;
    case 'subtract':
      result = subtract(bignumber(firstNumber), bignumber(secondNumber));
      break;
    case 'multiply':
      result = multiply(bignumber(firstNumber), bignumber(secondNumber)) as BigNumber;
      break;
    case 'divide':
      result = divide(bignumber(firstNumber), bignumber(secondNumber)) as BigNumber;
      break;
    default:
      return 0;
  }
  return parseFloat(result.toFixed(precision));
}
