/**
 * loader.mjs — md2hwpx 브라우저 엔진을 Node 에서 그대로 구동하는 샌드박스 로더
 *
 * md2hwpx 의 parser/presetManager/hwpxBuilder 는 `window.X = (()=>{...})()` 형태의
 * 브라우저 모듈이지만 DOM 의존이 사실상 없다(본문은 string-concat 으로 생성). 따라서
 * `{ window: self }` 한 줄 shim + JSZip + marked 만 주입하면 엔진 코드를 0줄도 고치지
 * 않고 Node 에서 동일하게 돌릴 수 있다. (CeoBriefing 이 브라우저에서 하던 것과 동일 경로)
 *
 * 외부 의존: Node 18+ (전역 Blob/TextEncoder/atob 필요 — generateAsync({type:'blob'}) 호환).
 */
import fs from 'node:fs';
import vm from 'node:vm';
import path from 'node:path';
import { fileURLToPath } from 'node:url';

const ENGINE_DIR = path.join(path.dirname(fileURLToPath(import.meta.url)), 'engine');
const read = (name) => fs.readFileSync(path.join(ENGINE_DIR, name), 'utf8');

/**
 * 엔진을 로드하고 핵심 객체를 반환한다.
 * @returns {{ MdParser, PresetManager, HwpxBuilder, JSZip, marked, TableFit, sandbox }}
 */
export function loadEngine() {
  if (typeof Blob === 'undefined' || typeof TextEncoder === 'undefined') {
    throw new Error('Node 18+ 필요 (전역 Blob/TextEncoder 미존재). 현재: ' + process.version);
  }

  // 브라우저 유사 전역 — window === self === globalThis === sandbox 자기참조
  const sandbox = {
    console, Blob, TextEncoder, TextDecoder, atob, btoa,
    setTimeout, clearTimeout, setInterval, clearInterval,
    setImmediate, clearImmediate, queueMicrotask,
    URL, Uint8Array, Uint16Array, Int32Array, Float64Array, ArrayBuffer, DataView,
    Promise, Math, Date, JSON, RegExp, Map, Set, WeakMap, Error,
  };
  sandbox.window = sandbox;
  sandbox.self = sandbox;
  sandbox.globalThis = sandbox;
  vm.createContext(sandbox);

  // UMD 모듈(JSZip/marked/table-fit): module.exports 경로로 받게 해 두고 실행
  const runUMD = (code) => {
    sandbox.module = { exports: {} };
    sandbox.exports = sandbox.module.exports;
    vm.runInContext(code, sandbox);
    const out = sandbox.module.exports;
    delete sandbox.module;
    delete sandbox.exports;
    return out;
  };
  // 브라우저 IIFE 모듈(parser/presetManager/hwpxBuilder): window.X 에 자기등록
  const runBrowser = (code) => vm.runInContext(code, sandbox);

  // 1) 의존 라이브러리
  sandbox.JSZip = runUMD(read('jszip.min.js'));
  sandbox.marked = sandbox.marked || runUMD(read('marked.min.js'));
  runUMD(read('table-fit.js')); // node 분기에서 module.exports + 브라우저 분기에서 window.TableFit

  // 2) md2hwpx 엔진 3모듈 (순서: parser → presetManager → hwpxBuilder)
  runBrowser(read('parser.js'));        // → window.MdParser
  runBrowser(read('presetManager.js')); // → window.PresetManager
  runBrowser(read('hwpxBuilder.js'));   // → window.HwpxBuilder

  const need = { MdParser: sandbox.MdParser, PresetManager: sandbox.PresetManager, HwpxBuilder: sandbox.HwpxBuilder, JSZip: sandbox.JSZip, marked: sandbox.marked };
  for (const [k, v] of Object.entries(need)) {
    if (!v) throw new Error(`엔진 로드 실패: ${k} 미정의 (engine/ 스냅샷 확인)`);
  }
  if (typeof sandbox.marked.lexer !== 'function') throw new Error('marked.lexer 미존재 — marked.min.js 손상');

  return { ...need, TableFit: sandbox.TableFit, sandbox };
}
