import path from "path";
import fs from "fs";
import { ICreateJsonFileParams } from "../types";

/**
 * 不存在的文件夹则创建
 * @param {string} path
 */
export const notExistsToCreateFile = (path: string) => {
  if (fs.existsSync(path)) return;
  fs.mkdirSync(path);
};

/**
 * 获取json文件 并返回 [[key,value],[key,value]...]]
 * @param {*} path
 * @returns
 */
export const readJsonFileSync = async (path: string) => {
  try {
    if (!fs.existsSync(path)) return {};
    const jsonStr = await fs.readFileSync(path, "utf8");
    // 将JSON字符串解析为对象
    return JSON.parse(jsonStr);
  } catch (error) {
    console.error("解析JSON时出错:", error);
    return {};
  }
};

/**
 * 创建json文件
 * @param {string} fileName 文件名
 * @param {string} folderName  文件夹名
 * @param {string} language 语言环境
 * @param {object} jsonData 文件数据
 */
export const createJsonFile = (params: ICreateJsonFileParams) => {
  const { fileName, folderName, jsonData, language } = params;
  notExistsToCreateFile(folderName);
  notExistsToCreateFile(path.resolve(`${folderName}/${language}`));
  fs.writeFileSync(
    path.resolve(`${folderName}/${language}/${fileName}`),
    JSON.stringify(jsonData, null, 2),
    "utf8"
  );
};

export const getRandomNumber = (min: number, max: number) => {
  return Math.floor(Math.random() * (max - min + 1)) + min;
};

export const isDirectoryPath = (path: string) => {
  if (!fs.existsSync(path)) return false;
  return fs.statSync(path).isDirectory();
};

export const readFileOfDirSync = (dirPath: string) => {
  if (!isDirectoryPath(dirPath)) return [];
  const files = fs.readdirSync(dirPath);
  // 筛选出所有文件夹
  return files.filter((file) => path.extname(file) === ".json");
};

export function chunkArray<T extends object>(array: T[], chunkSize: number) {
  const result = [];
  let index = 0;

  while (index < array.length) {
    result.push(array.slice(index, index + chunkSize));
    index += chunkSize;
  }
  return result;
}

export function intersection<T>(arr1: T[], arr2: T[]): T[] {
  const setA = new Set(arr1);
  const setB = new Set(arr2);
  // 创建一个新的 Set 来存储交集
  let intersectionSet = new Set<T>();

  // 遍历较小的集合，检查每个元素是否在另一个集合中
  for (let item of setA) {
    if (setB.has(item)) {
      intersectionSet.add(item);
    }
  }

  return [...intersectionSet];
}

/**
 * 扁平化嵌套 JSON 对象，使用点符号作为键
 * @param obj 要扁平化的对象
 * @param prefix 键前缀
 * @returns 扁平化后的对象
 */
export const flattenJson = (
  obj: any,
  prefix: string = ""
): Record<string, string> => {
  const flattened: Record<string, string> = {};

  for (const key in obj) {
    if (obj.hasOwnProperty(key)) {
      const newKey = prefix ? `${prefix}.${key}` : key;

      if (
        typeof obj[key] === "object" &&
        obj[key] !== null &&
        !Array.isArray(obj[key])
      ) {
        // 递归处理嵌套对象
        Object.assign(flattened, flattenJson(obj[key], newKey));
      } else {
        // 直接赋值字符串、数字等基本类型
        flattened[newKey] = String(obj[key]);
      }
    }
  }

  return flattened;
};

/**
 * 检测扁平化JSON中是否存在路径冲突
 * @param flatObj 扁平化的对象
 * @returns 是否存在冲突
 */
const hasPathConflicts = (flatObj: Record<string, string>): boolean => {
  const keys = Object.keys(flatObj);

  for (let i = 0; i < keys.length; i++) {
    for (let j = i + 1; j < keys.length; j++) {
      const key1 = keys[i];
      const key2 = keys[j];

      // 检查是否一个key是另一个key的前缀
      if (key1.startsWith(key2 + ".") || key2.startsWith(key1 + ".")) {
        return true;
      }
    }
  }

  return false;
};

/**
 * 将扁平化的 JSON 重构为嵌套结构
 * @param flatObj 扁平化的对象
 * @returns 重构后的嵌套对象
 */
export const unflattenJson = (flatObj: Record<string, string>): any => {
  // 如果存在路径冲突，直接返回扁平化结构，不进行反扁平化
  if (hasPathConflicts(flatObj)) {
    console.warn(
      "Path conflicts detected in JSON structure, returning flattened structure"
    );
    return flatObj;
  }

  const result: any = {};

  for (const key in flatObj) {
    if (flatObj.hasOwnProperty(key)) {
      const keys = key.split(".");
      let current = result;

      for (let i = 0; i < keys.length - 1; i++) {
        const k = keys[i];
        if (!(k in current)) {
          current[k] = {};
        }
        current = current[k];
      }

      current[keys[keys.length - 1]] = flatObj[key];
    }
  }

  return result;
};
