import { execFile } from "node:child_process";
import { mkdtemp, readFile, readdir, rm } from "node:fs/promises";
import { tmpdir } from "node:os";
import { dirname, join, resolve } from "node:path";
import { fileURLToPath } from "node:url";
import { promisify } from "node:util";

const execFileAsync = promisify(execFile);
const root = resolve(dirname(fileURLToPath(import.meta.url)), "..");
const pwaRoot = join(root, "apps", "pwa");
const viteCli = join(root, "node_modules", "vite", "bin", "vite.js");
const developmentPatterns = [
  /\/@vite\/client/,
  /react-refresh/i,
  /connection-dev-bypass/,
  /Continue in developer mode/,
  /개발자 모드로 계속/
];

function releaseError(code) {
  const error = new Error(code);
  error.stack = code;
  return error;
}

async function filesBelow(directory, current = directory) {
  const files = [];
  for (const entry of await readdir(current, { withFileTypes: true })) {
    const path = join(current, entry.name);
    if (entry.isDirectory()) files.push(...await filesBelow(directory, path));
    else if (entry.isFile()) files.push(path);
    else throw releaseError("release_pwa_policy_failed");
  }
  return files;
}

function utf8Text(value) {
  try {
    return new TextDecoder("utf-8", { fatal: true }).decode(value);
  } catch {
    throw releaseError("release_pwa_development_artifact");
  }
}

export async function assertProductionPwa({ pwaDir }) {
  try {
    const files = await filesBelow(resolve(pwaDir));
    for (const path of files) {
      if (/\.map$/i.test(path)) throw releaseError("release_pwa_development_artifact");
      if (!/\.(?:html|[cm]?js)$/i.test(path)) continue;
      const text = utf8Text(await readFile(path));
      if (developmentPatterns.some((pattern) => pattern.test(text))) {
        throw releaseError("release_pwa_development_artifact");
      }
    }
    return { files: files.length };
  } catch (error) {
    if (error?.message === "release_pwa_development_artifact" ||
        error?.message === "release_pwa_policy_failed") throw error;
    throw releaseError("release_pwa_policy_failed");
  }
}

export async function runReleasePreflight() {
  let output;
  try {
    output = await mkdtemp(join(tmpdir(), "crm-release-preflight-"));
    try {
      await execFileAsync(process.execPath, [viteCli, "build", "--outDir", output, "--emptyOutDir"], {
        cwd: pwaRoot,
        windowsHide: true
      });
    } catch {
      throw releaseError("release_pwa_build_failed");
    }
    await assertProductionPwa({ pwaDir: output });
  } finally {
    if (output) await rm(output, { recursive: true, force: true }).catch(() => {});
  }
}

if (process.argv[1] && resolve(process.argv[1]) === fileURLToPath(import.meta.url)) {
  runReleasePreflight()
    .then(() => console.log("Production PWA policy passed."))
    .catch((error) => {
      console.error(error.message);
      process.exitCode = 1;
    });
}
