const fs = require("fs");
const path = require("path");
const parser = require("@babel/parser");
const traverse = require("@babel/traverse").default;

const projectRoot = path.resolve(__dirname, "..", "..");
const bundlePath = path.join(projectRoot, "assets", "index-CO3BwsT2.js");
const outputRoot = path.resolve(__dirname, "..", "output");

const source = fs.readFileSync(bundlePath, "utf8");
const ast = parser.parse(source, {
  sourceType: "module",
  plugins: [
    "jsx",
    "classProperties",
    "classPrivateProperties",
    "classPrivateMethods",
    "optionalChaining",
    "nullishCoalescingOperator",
    "dynamicImport",
    "topLevelAwait",
  ],
  errorRecovery: true,
});

const importedChunks = new Set();
const stringLiterals = new Map();
const apiCandidates = new Set();
const routeCandidates = new Set();
const componentCandidates = new Set();

function bump(map, value) {
  map.set(value, (map.get(value) || 0) + 1);
}

traverse(ast, {
  ImportExpression(path) {
    const sourceNode = path.node.source;
    if (sourceNode.type === "StringLiteral") {
      importedChunks.add(sourceNode.value);
    }
  },
  StringLiteral(path) {
    const value = path.node.value;
    if (!value || value.length < 2) {
      return;
    }

    if (value.startsWith("/api/")) {
      apiCandidates.add(value);
    }

    if (value.startsWith("/") && /[a-z]/i.test(value)) {
      if (!value.includes(".")) {
        routeCandidates.add(value);
      }
    }

    if (/^[A-Z][A-Za-z0-9]+$/.test(value) && value.length < 40) {
      componentCandidates.add(value);
    }

    bump(stringLiterals, value);
  },
  TemplateElement(path) {
    const value = path.node.value.raw;
    if (value.includes("/api/")) {
      apiCandidates.add(value);
    }
  },
});

const topStrings = [...stringLiterals.entries()]
  .filter(([value]) => value.length <= 120)
  .sort((a, b) => b[1] - a[1])
  .slice(0, 300)
  .map(([value, count]) => ({ value, count }));

const report = {
  bundlePath,
  importedChunks: [...importedChunks].sort(),
  apiCandidates: [...apiCandidates].sort(),
  routeCandidates: [...routeCandidates].sort(),
  componentCandidates: [...componentCandidates].sort(),
  topStrings,
};

fs.mkdirSync(outputRoot, { recursive: true });
fs.writeFileSync(
  path.join(outputRoot, "bundle-report.json"),
  JSON.stringify(report, null, 2),
  "utf8",
);

console.log(`report: ${path.join(outputRoot, "bundle-report.json")}`);
