import Vue from "vue";
import CryptoJS from "crypto-js";
import moment from "moment";
import { find, get } from "lodash-es";

// 加密数据
export let encrypt = (str, keyStr, ivStr) => {
  keyStr = keyStr ? keyStr : "0000000671595991";
  ivStr = ivStr ? ivStr : "tdrdadq59tbss5n7";
  //密钥16位
  let key = CryptoJS.enc.Utf8.parse(keyStr);
  //加密向量16位
  let iv = CryptoJS.enc.Utf8.parse(ivStr);
  let encrypted = CryptoJS.AES.encrypt(str, key, {
    iv: iv,
    mode: CryptoJS.mode.CBC,
    padding: CryptoJS.pad.Pkcs7,
  });

  return encrypted.toString();
};

// 解密
export const decrypt = (word, keyStr, ivStr) => {
  keyStr = keyStr ? keyStr : "0000000671595991";
  ivStr = ivStr ? ivStr : "tdrdadq59tbss5n7";
  let key = CryptoJS.enc.Utf8.parse(keyStr);
  let iv = CryptoJS.enc.Utf8.parse(ivStr);

  let decrypt = CryptoJS.AES.decrypt(word, key, {
    iv,
    mode: CryptoJS.mode.CBC,
    padding: CryptoJS.pad.Pkcs7,
  });
  return decrypt.toString(CryptoJS.enc.Utf8);
};

/**
 * 加密存储临时数据并解析对象
 */
const aseKey = "**_FXxx_1234_KEY";
const KEY = "KEY_EXTRA";
export class SessionCrypto {
  // 加密
  static setItem(key = KEY, value = "") {
    if (typeof key === "string") {
      const stringify = JSON.stringify(value);
      const encrypt = CryptoJS.AES.encrypt(
        stringify,
        CryptoJS.enc.Utf8.parse(aseKey),
        {
          mode: CryptoJS.mode.ECB,
          padding: CryptoJS.pad.Pkcs7,
        }
      ).toString();
      window.sessionStorage.setItem(key, encrypt);
      return encrypt;
    }
  }
  // 解密
  static getItem(key = KEY) {
    const ssStr = window.sessionStorage.getItem(key) || "";
    try {
      if (ssStr) {
        const decrypt = CryptoJS.AES.decrypt(
          ssStr,
          CryptoJS.enc.Utf8.parse(aseKey),
          {
            mode: CryptoJS.mode.ECB,
            padding: CryptoJS.pad.Pkcs7,
          }
        ).toString(CryptoJS.enc.Utf8);
        const parseStr = JSON.parse(decrypt);
        return parseStr;
      }
      return "";
    } catch (e) {
      return "";
    }
  }
  // 删除
  static remove(key) {
    window.sessionStorage.removeItem(key);
  }
}

// 表单重置
export function resetForm(refName) {
  if (this.$refs[refName]) {
    this.$refs[refName].resetFields();
  }
}

// 表格清除选中
export function clearSelection(refName) {
  if (this.$refs[refName]) {
    this.$refs[refName].clearSelection();
  }
}

/**
 * 对象数组去重
 * @param {数组} arr
 * @param {判断字段} field
 */
export function uniqueFunc(arr, field) {
  const res = new Map();
  return arr.filter((item) => !res.has(item[field]) && res.set(item[field], 1));
}

// 递归获取底层子数组
export function findBottomSubarrays(arr) {
  let bottomSubarrays = [];
  function recursiveSearch(subArr) {
    for (let item of subArr) {
      if (item.children && item.children.length) {
        recursiveSearch(item.children);
      } else {
        bottomSubarrays.push(...subArr);
        break;
      }
    }
  }
  recursiveSearch(arr);
  return bottomSubarrays;
}

// 秒数转HH:mm:ss
export function formatSeconds(secondsNum) {
  const time = moment.duration(secondsNum, "seconds");
  const hours = time.hours();
  const minutes = time.minutes();
  const seconds = time.seconds();
  return moment({ h: hours, m: minutes, s: seconds }).format("HH:mm:ss");
}

/**
 *
 * @param {*} fn 数据获取函数
 * @param {*} searchForm 搜索表单
 * @param {*} callback  回调函数
 */
export const dataSection = async (fn, searchForm = {}, callback) => {
  let dataList = [];
  let page = 1;
  let size = 1000;
  let execute = async () => {
    let { data, total } = await fn({ page, size, ...searchForm });
    dataList = [...dataList, ...data];
    Vue.prototype.$app.loading = true;
    Vue.prototype.$app.percentage = parseInt((dataList.length / total) * 100);
    if (dataList.length >= total || data.length == 0) {
      if (callback) callback(dataList);
      Vue.prototype.$app.loading = false;
      Vue.prototype.$app.percentage = 1;
      return;
    }
    setTimeout(() => {
      page += 1;
      execute();
    });
  };
  execute();
};

// 构建树形数据
export function buildTree(data, idField = "id", parentIdField = "parentId") {
  const idToItem = {};
  data.forEach((item) => {
    idToItem[item[idField]] = { ...item, childList: [] };
  });

  const tree = [];
  data.forEach((item) => {
    const parentId = item[parentIdField];
    if (parentId === null || parentId === 0) {
      tree.push(idToItem[item[idField]]);
    } else {
      const parent = idToItem[parentId];
      if (parent) {
        parent.childList.push(idToItem[item[idField]]);
      } else {
        tree.push(idToItem[item[idField]]);
      }
    }
  });

  return tree;
}

// 递归从数组里边取出某一字段
export const getFieldFromArray = (arr, field, treeField) => {
  let result = [];
  arr.forEach((item) => {
    if (item[field]) {
      result.push(item[field]);
    }

    // 如果有子路由，递归提取子路由的路径
    if (item[treeField] && item[treeField].length > 0) {
      result = result.concat(
        getFieldFromArray(item[treeField], field, treeField)
      );
    }
  });

  return result;
};

// 生成路由
export const generateRoutes = (menuList) => {
  let routers = menuList.map((item) => {
    // 构造符合要求的结构
    let path = item.url.charAt(0) === "/" ? item.url : "/" + item.url;
    let name = item.url.replace(/^\//, "");
    let activeMenu = item.activeDir
      ? "/" + item.activeDir.replace(/^\//, "")
      : "";
    let component = item.component ? item.component.replace(/^\//, "") : null;
    const newItem = {
      path,
      name,
      hidden: !!item.visible,
      hideChildrenInMenu: !!item.hideChildrenInMenu,
      component: () => import(`@/${component}`),
      meta: {
        title: item.name,
        icon: item.imgPath,
        keepAlive: !!item.cache,
        activeMenu,
      },
    };
    // 递归处理子节点
    if (item.children && item.children.length > 0) {
      newItem.children = generateRoutes(item.children);
    }
    return newItem;
  });
  routers.forEach((v) => {
    if (v.children && v.children.length) {
      v.redirect = v.children[0].path;
    }
  });
  return routers;
};
/**
 * 过滤菜单按钮项并提取 menuType = 2 的项
 * @param {Array} menuList - 菜单列表
 * @param {Boolean} menuType - true 获取 menuType = 2 的项并返回为一维数组, false 剔除 menuType = 2 的项
 * @param {Array} btnItems - 用于存储 menuType = 2 的项（递归使用）
 * @returns {Array} - 返回提取到的 menuType = 2 的项（如果 menuType 为 true）或剔除 menuType = 2 的菜单
 */
export const filterBtn = (menuList, menuType = true, btnItems = []) => {
  const result = menuList
    .map((menu) => {
      // 深拷贝对象，避免修改原数据
      const newMenu = { ...menu };
      if (newMenu.children && newMenu.children.length > 0) {
        newMenu.children = filterBtn(newMenu.children, menuType, btnItems);
      }
      const btnItem = newMenu.menuType == 2;

      if (menuType) {
        if (btnItem) {
          btnItems.push(newMenu);
        }
        return newMenu;
      } else {
        // 剔除 menuType = 2 的项
        return !btnItem ? newMenu : null;
      }
    })
    .filter((menu) => menu !== null); // 过滤掉 null 项
  return menuType ? btnItems : result;
};

export function findInTree(data, key, value) {
  // 递归遍历树形结构
  function recursiveSearch(nodes) {
    return find(nodes, (node) => {
      if (get(node, key) === value) {
        return true;
      }
      if (node.children) {
        return recursiveSearch(node.children);
      }
      return false;
    });
  }

  return recursiveSearch(data);
}
