import fs from "node:fs/promises";
import path from "node:path";

const repoRoot = process.cwd();
const kitRoot = path.join(repoRoot, "preview-kits/baseui");
const outFile = path.join(repoRoot, "lib/preview/generated/baseui-files.ts");
const extensions = new Set([".ts", ".tsx", ".js", ".jsx", ".css", ".json"]);

async function main() {
  const packageJson = JSON.parse(
    await fs.readFile(path.join(kitRoot, "package.json"), "utf8"),
  ) as { dependencies?: Record<string, string> };
  const files = await collectFiles(kitRoot);
  const entries = await Promise.all(
    files.map(async (absolutePath) => {
      const virtualPath = path
        .relative(kitRoot, absolutePath)
        .split(path.sep)
        .join("/");
      return [virtualPath, await fs.readFile(absolutePath, "utf8")] as const;
    }),
  );

  entries.sort(([left], [right]) => left.localeCompare(right));

  await fs.mkdir(path.dirname(outFile), { recursive: true });
  await fs.writeFile(
    outFile,
    [
      "// Generated by scripts/preview/generate-baseui-files.ts.",
      "// Source of truth: preview-kits/baseui/**",
      "export const baseuiPreviewFiles: Record<string, string> = ",
      JSON.stringify(Object.fromEntries(entries), null, 2),
      ";\n",
      "export const baseuiPreviewDependencies: Record<string, string> = ",
      JSON.stringify(packageJson.dependencies ?? {}, null, 2),
      ";\n",
    ].join("\n"),
  );

  console.log(`Generated ${entries.length} Base UI preview files.`);
}

async function collectFiles(directory: string): Promise<Array<string>> {
  const entries = await fs.readdir(directory, { withFileTypes: true });
  const files = await Promise.all(
    entries.map(async (entry) => {
      const absolutePath = path.join(directory, entry.name);

      if (entry.isDirectory()) {
        if (entry.name === "node_modules" || entry.name === ".next") {
          return [];
        }

        return collectFiles(absolutePath);
      }

      if (entry.isFile() && extensions.has(path.extname(entry.name))) {
        return [absolutePath];
      }

      return [];
    }),
  );

  return files.flat().sort();
}

void main();
