const fs = require("fs");
const path = require("path");
const { defineConfig } = require("vite");
const { viteSingleFile } = require("vite-plugin-singlefile");
const JavaScriptObfuscator = require("javascript-obfuscator");

const platformBuilds = {
  applovin: { adapter: "applovin", output: "applovin" },
  unity: { adapter: "unity", output: "unity" },
  playturbo: { adapter: "playturbo", output: "playturbo" },
  mintegral: { adapter: "playturbo", output: "mintegral" },
  google: { adapter: "google", output: "google" },
};

// ── JS 混淆：base64 载荷保护 + 代码混淆 ─────────────────────────
function obfuscateJsInHtml(html) {
  const scriptRegex = /(<script>)([\s\S]*?)(<\/script>)/;
  const match = html.match(scriptRegex);
  if (!match) return html;

  let jsCode = match[2];

  // 1. 找出所有 base64 数据载荷，替换为短占位符，确保 JS 语法完整
  const b64Payloads = [];
  const b64Pattern = /(data:(?:image|audio)\/[^;]*?;base64,)([A-Za-z0-9+/=]+)/g;
  let b64Match;
  while ((b64Match = b64Pattern.exec(jsCode)) !== null) {
    const idx = b64Payloads.length;
    b64Payloads.push(b64Match[2]);
    jsCode =
      jsCode.slice(0, b64Match.index + b64Match[1].length) +
      `__B64_${idx}__` +
      jsCode.slice(b64Match.index + b64Match[1].length + b64Match[2].length);
    // 重置 regex lastIndex（因为替换改变了字符串长度）
    b64Pattern.lastIndex = b64Match.index + b64Match[1].length + `__B64_${idx}__`.length;
  }

  console.log(`[obfuscate] Found ${b64Payloads.length} base64 payloads, total ${b64Payloads.reduce((s, p) => s + p.length, 0).toLocaleString()} bytes`);

  // 2. 混淆 JS（stringArrayThreshold: 0 确保占位符不被编码到 stringArray）
  const result = JavaScriptObfuscator.obfuscate(jsCode, {
    compact: true,
    controlFlowFlattening: false,       // 不影响 WebGL 帧率
    deadCodeInjection: false,            // 不增加体积
    debugProtection: false,              // 不用 setInterval 浪费 CPU
    disableConsoleOutput: true,
    identifierNamesGenerator: "hexadecimal",
    log: false,
    numbersToExpressions: false,
    renameGlobals: false,
    selfDefending: false,                // 暂时关闭排查语法错误
    simplify: true,
    splitStrings: false,
    stringArray: false,                  // 关闭 stringArray，保护占位符
    transformObjectKeys: false,
    unicodeEscapeSequence: false,
  });

  let obfuscatedJs = result.getObfuscatedCode();

  // 3. 恢复 base64 载荷
  for (let i = 0; i < b64Payloads.length; i++) {
    obfuscatedJs = obfuscatedJs.replace(`__B64_${i}__`, b64Payloads[i]);
  }

  return html.replace(scriptRegex, match[1] + obfuscatedJs + match[3]);
}

// ── 构建后处理 ───────────────────────────────────────────────────
function patchSingleFileHtml(htmlPath) {
  if (!fs.existsSync(htmlPath)) return;
  let html = fs.readFileSync(htmlPath, "utf8");

  // 1. 移除 HTML 注释
  html = html.replace(/<!--[\s\S]*?-->/g, "");

  // 2. 清理标签属性（移除 type="module" / crossorigin）
  html = html
    .replace(/<script\s+type="module"\s+crossorigin>/g, "<script>")
    .replace(/<script\s+crossorigin\s+type="module">/g, "<script>")
    .replace(/<script\s+type="module">/g, "<script>")
    .replace(/<script\s+crossorigin>/g, "<script>")
    .replace(/<style\s+rel="stylesheet"\s+crossorigin>/g, "<style>")
    .replace(/<style\s+crossorigin\s+rel="stylesheet">/g, "<style>")
    .replace(/<style\s+crossorigin>/g, "<style>");

  // 3. JS 混淆
  html = obfuscateJsInHtml(html);

  fs.writeFileSync(htmlPath, html);
}

function finalizeHtmlPlugin(outDir) {
  return {
    name: "finalize-html-output",
    closeBundle() {
      const htmlPath = path.resolve(__dirname, outDir, "index.html");
      patchSingleFileHtml(htmlPath);
    },
  };
}

module.exports = defineConfig(({ mode }) => {
  const platformBuild = platformBuilds[mode];
  const adapter = platformBuild?.adapter || "google";
  const output = platformBuild?.output;
  const outDir = output ? `dist/${output}` : "dist";

  return {
    plugins: [viteSingleFile(), finalizeHtmlPlugin(outDir)],
    server: {
      allowedHosts: ["color2.jccytech.cn", "localhost", ".jccytech.cn"],
    },
    resolve: {
      alias: {
        "#ad-config": path.resolve(
          __dirname,
          process.env.AD_CONFIG_PATH || "src/filler/ad-config.ts",
        ),
        "./ad-platform/current": path.resolve(
          __dirname,
          `src/filler/ad-platform/adapters/${adapter}.ts`,
        ),
      },
    },
    esbuild: {
      drop: ["console", "debugger"],
      legalComments: "none",
    },
    build: {
      sourcemap: false,
      assetsInlineLimit: 100 * 1024 * 1024,
      target: "es2017",
      outDir,
      emptyOutDir: true,
      rollupOptions: {
        input: {
          main: "./index.html",
        },
        output: {
          entryFileNames: "assets/[name].js",
          chunkFileNames: "assets/[name].js",
          assetFileNames: "assets/[name][extname]",
        },
      },
    },
  };
});
