const fs = require("node:fs");
const path = require("node:path");

const { log } = require("./logger");
const { ERROR, asFailure } = require("./errors");
const { validateInput } = require("./validate");
const { renderToPDF } = require("./render_pdf");

function parseArgs(argv) {
  const args = { inPath: null, outPath: null };
  for (let i = 2; i < argv.length; i++) {
    const a = argv[i];
    if (a === "--in") args.inPath = argv[++i];
    else if (a === "--out") args.outPath = argv[++i];
  }
  return args;
}

async function main() {
  const { inPath, outPath } = parseArgs(process.argv);
  if (!inPath || !outPath) {
    log(asFailure(ERROR.BAD_INPUT, "missing_cli_args"));
    process.exitCode = 2;
    return;
  }

  let inputRaw;
  try {
    inputRaw = fs.readFileSync(inPath, "utf8");
  } catch {
    log(asFailure(ERROR.BAD_INPUT, "read_input_failed"));
    process.exitCode = 2;
    return;
  }

  let input;
  try {
    input = JSON.parse(inputRaw);
  } catch {
    log(asFailure(ERROR.BAD_INPUT, "parse_input_failed"));
    process.exitCode = 2;
    return;
  }

  const bad = validateInput(input);
  if (bad) {
    log(asFailure(bad, "validate_input_failed"));
    process.exitCode = 2;
    return;
  }

  const started = process.hrtime.bigint();
  log({ event: "start", repo: `${input.repoMeta.owner}/${input.repoMeta.repo}`, path: input.repoMeta.path });

  try {
    const { pdf, blockedRequests, mermaidCount } = await renderToPDF(input);
    fs.mkdirSync(path.dirname(outPath), { recursive: true });
    fs.writeFileSync(outPath, pdf);
    const elapsedMs = Number((process.hrtime.bigint() - started) / 1000000n);
    log({ event: "done", bytes: pdf.length, ms: elapsedMs, blocked_requests: blockedRequests, mermaid_count: mermaidCount });
  } catch (e) {
    const safe = e && typeof e === "object" && e.safeError ? e.safeError : null;
    if (safe) {
      log(safe);
      process.exitCode = 1;
      return;
    }
    log(asFailure(ERROR.INTERNAL, "unhandled_exception"));
    process.exitCode = 1;
  }
}

main();
