import { existsSync } from "node:fs";
import * as fs from "node:fs/promises";
import nodePath from "node:path";
import { fileURLToPath } from "node:url";
async function writeJson(path, data) {
  await fs.writeFile(path, JSON.stringify(data, null, "	"), { encoding: "utf-8" });
}
async function removeDir(dir) {
  await fs.rm(dir, { recursive: true, force: true, maxRetries: 3 });
}
async function emptyDir(dir) {
  await removeDir(dir);
  await fs.mkdir(dir, { recursive: true });
}
async function getFilesFromFolder(dir) {
  const data = await fs.readdir(dir, { withFileTypes: true });
  let files = [];
  for (const item of data) {
    if (item.isDirectory()) {
      const moreFiles = await getFilesFromFolder(new URL(`./${item.name}/`, dir));
      files = files.concat(moreFiles);
    } else {
      files.push(new URL(`./${item.name}`, dir));
    }
  }
  return files;
}
async function copyFilesToFolder(files, outDir, exclude = []) {
  const excludeList = exclude.map(fileURLToPath);
  const fileList = files.map(fileURLToPath).filter((f) => !excludeList.includes(f));
  if (files.length === 0) throw new Error("No files found to copy");
  let commonAncestor = nodePath.dirname(fileList[0]);
  for (const file of fileList.slice(1)) {
    while (!file.startsWith(commonAncestor)) {
      commonAncestor = nodePath.dirname(commonAncestor);
    }
  }
  for (const origin of fileList) {
    const dest = new URL(nodePath.relative(commonAncestor, origin), outDir);
    const realpath = await fs.realpath(origin);
    const isSymlink = realpath !== origin;
    const isDir = (await fs.stat(origin)).isDirectory();
    if (isDir && !isSymlink) {
      await fs.mkdir(new URL("..", dest), { recursive: true });
    } else {
      await fs.mkdir(new URL(".", dest), { recursive: true });
    }
    if (isSymlink) {
      const realdest = fileURLToPath(new URL(nodePath.relative(commonAncestor, realpath), outDir));
      const target = nodePath.relative(fileURLToPath(new URL(".", dest)), realdest);
      if (!existsSync(dest)) {
        await fs.symlink(target, dest, isDir ? "dir" : "file");
      }
    } else if (!isDir) {
      await fs.copyFile(origin, dest);
    }
  }
  return commonAncestor;
}
export {
  copyFilesToFolder,
  emptyDir,
  getFilesFromFolder,
  removeDir,
  writeJson
};
