/*
 * @Author: your name
 * @Date: 2022-01-13 17:09:05
 * @LastEditTime: 2025-04-17 11:01:43
 * @LastEditors: code4eat awesomedema@gmail.com
 * @Description: 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
 * @FilePath: /KC-MiddlePlatform/src/utils.js
 */

import axios, { AxiosResponse } from 'axios';
import { Key } from 'react';

/**
 * 生成指定长度的随机字符串
 * @param length 字符串长度
 * @returns 随机字符串
 */
export const randomString = (length: number): string => {
  const chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_=-';
  return Array.from(
    { length },
    () => chars[Math.floor(Math.random() * chars.length)]
  ).join('');
};

export interface TreeItemType {
  children?: TreeItemType[];
  [key: string]: any;
}

/**
 * 从树结构中获取指定键的所有值
 * @param data 树结构数据
 * @param key 要获取的键名
 * @returns 值的数组
 */
export const getValsFromTree = (data: TreeItemType[], key: string): any[] => {
  const result: any[] = [];
  
  const traverse = (nodes: TreeItemType[]): void => {
    nodes.forEach((node) => {
      if (node[key]) {
        result.push(node[key]);
      }
      if (node.children?.length) {
        traverse(node.children);
      }
    });
  };

  traverse(data);
  return result;
};

export const searchTree = (treeData: TreeItemType[]) => {};

/**
 * 下载模板文件
 * @param path 文件路径
 */
export const downloadTemplateReq = async (path: string): Promise<void> => {
  try {
    const userData = localStorage.getItem('userData');
    const { token = '' } = JSON.parse(userData || '{}');

    const response: AxiosResponse = await axios({
      method: 'get',
      url: `/gateway/${path}`,
      responseType: 'blob',
      headers: { token },
    });

    const filename = decodeURI(response.headers['content-disposition']);
    const blob = new Blob([response.data], {
      type: 'application/vnd.ms-excel',
    });
    const objectUrl = URL.createObjectURL(blob);
    
    const link = document.createElement('a');
    link.download = `${filename}.xls`;
    link.href = objectUrl;
    link.style.display = 'none';
    document.body.appendChild(link);
    link.click();
    document.body.removeChild(link);
    URL.revokeObjectURL(objectUrl);
  } catch (error) {
    console.error('下载模板失败:', error);
    throw error;
  }
};

/**
 * 获取树结构中最深的节点及其父节点
 * @param tree 树结构
 * @param childrenName 子节点属性名
 * @returns [最深节点, 父节点]
 */
export const getDeepestTreeData = <T extends { [key: string]: any }>(
  tree: T,
  childrenName: string
): [T, T | undefined] => {
  let parent: T | undefined;
  
  const traverse = (node: T): T => {
    if (node[childrenName]?.length) {
      parent = node;
      return traverse(node[childrenName][0]);
    }
    return node;
  };

  return [traverse(tree), parent];
};

/**
 * 数组去重
 * @param arr 数组
 * @param uniId 唯一标识字段
 * @returns 去重后的数组
 */
export const uniqueFunc = <T extends { [key: string]: any }>(arr: T[], uniId: string): T[] => {
  const uniqueMap = new Map();
  return arr.filter((item) => !uniqueMap.has(item[uniId]) && uniqueMap.set(item[uniId], 1));
};

//获取树结构的所有叶子节点

interface TreeNode {
  [key: string]: any;
  child?: TreeNode[];
}

/**
 * 获取树的所有叶子节点
 * @param node 树节点
 * @param leaves 叶子节点数组
 * @returns 叶子节点数组
 */
export const getLeafNodes = (node: TreeNode, leaves: TreeNode[] = []): TreeNode[] => {
  if (!node.child?.length) {
    leaves.push(node);
  } else {
    node.child.forEach((child) => getLeafNodes(child, leaves));
  }
  return leaves;
};

//根据树结构中的某个属性的集合，获取对应的节点，返回一个集合

/**
 * 根据属性值查找节点
 * @param node 树节点
 * @param keys 属性值集合
 * @param str 属性名
 * @returns 匹配的节点数组
 */
export const findNodesBySomes = (
  node: TreeNode,
  keys: Set<string | number>,
  str: string
): TreeNode[] => {
  const results: TreeNode[] = [];

  if (keys.has(node[str])) {
    results.push(node);
  }

  if (node.child?.length) {
    node.child.forEach((child) => {
      results.push(...findNodesBySomes(child, keys, str));
    });
  }

  return results;
};

//更改树结构集合的子集属性名

/**
 * 重命名子节点属性
 * @param nodes 节点数组
 * @param key 要重命名的属性名
 * @returns 处理后的节点数组
 */
export const renameChildListToChildren = <T extends { [key: string]: any; children?: T[] }>(
  nodes: T[],
  key: string
): T[] => {
  return nodes.map((node) => {
    const newNode = { ...node };
    if (newNode[key]?.length) {
      newNode.children = renameChildListToChildren(newNode[key], key);
    }
    return newNode;
  });
};

//获取目标节点的所有父节点，且以集合的方式返回

/**
 * 查找节点的所有父节点
 * @param tree 树结构
 * @param targetNodeKeyName 目标节点键名
 * @param targetNodeKeyVal 目标节点键值
 * @param path 路径
 * @returns 父节点数组或null
 */
export const findParents = (
  tree: TreeNode[],
  targetNodeKeyName: string,
  targetNodeKeyVal: Key,
  path: TreeNode[] = []
): TreeNode[] | null => {
  for (const node of tree) {
    if (node[targetNodeKeyName] === targetNodeKeyVal) {
      return [...path, node];
    }

    if (node.children?.length) {
      const result = findParents(node.children, targetNodeKeyName, targetNodeKeyVal, [...path, node]);
      if (result) return result;
    }
  }
  return null;
};

//搜索树结果

/**
 * 搜索树结构并保持结构
 * @param nodes 节点数组
 * @param keyName 键名
 * @param keyVal 键值
 * @returns 匹配的节点数组
 */
export const searchTreeAndKeepStructure = <T extends { [key: string]: any }>(
  nodes: T[],
  keyName: string,
  keyVal: any
): T[] => {
  return nodes.reduce<T[]>((result, node) => {
    if (String(node[keyName]).includes(String(keyVal))) {
      result.push({
        ...node,
        children: node.children?.length
          ? searchTreeAndKeepStructure(node.children, keyName, keyVal)
          : undefined,
      });
    } else if (node.children?.length) {
      const children = searchTreeAndKeepStructure(node.children, keyName, keyVal);
      if (children.length) {
        result.push({ ...node, children });
      }
    }
    return result;
  }, []);
};
