/**
 * render-fixture.ts から `renderFixture()`（node:fs 不要な純粋な文字列変換部分）だけを分離したモジュール。
 *
 * Why not: `renderFixture()` 自体は fs を使わないが、同じファイル内に `readFileSync`（node:fs）を使う
 * `loadFixtureSource` 等が同居していると、Vite の Browser Mode（実ブラウザ実行）ではモジュールの
 * import 時点で externalize された node:fs へのアクセスとして即座に例外になる
 * （named import の分割代入が読み込み時に評価されるため、実際に呼び出すかどうかは関係ない）。
 * jsdom 環境（vite-node/Node 実行）では問題なく動くため、fs を使う既存のヘルパー
 * （render-fixture.ts の loadFixtureSource / renderFixtureFile / mountFixture）はそのまま残し、
 * fs を一切 import しないこのファイルだけを Browser Mode のテストから直接 import できるようにする。
 */

export interface RenderFixtureOptions {
  /**
   * `{id}` に差し込むユニットID。既定値は 'test-unit-1'。
   */
  id?: string;
  /**
   * `{key}` / `{key@sub}` / `{key:filter#arg}` のうち、key 部分に対応する値を指定すると
   * その値に解決される。未指定のキーは空文字に解決する。
   */
  values?: Record<string, string>;
}

/**
 * カスタムフィールドメーカー生成の ACMS テンプレート構文入り HTML を、変数解決済みの近似 HTML に変換する。
 * 近似の限界（BEGIN_IF 分岐を評価しない・filter 記法を解決しない等）は render-fixture.ts の
 * モジュール doc コメントを参照。
 */
export function renderFixture(rawHtml: string, options: RenderFixtureOptions = {}): string {
  const { id = 'test-unit-1', values = {} } = options;

  let html = rawHtml;

  // <!-- BEGIN xxx:loop -->...<!-- END xxx:loop --> / <!-- BEGIN_IF [...] -->...<!-- ELSE -->...
  // <!-- END_IF --> など、BEGIN/ELSE/END から始まるブロックコメントはコメント自体だけを除去し、
  // 中身は展開したまま残す（条件・繰り返しは評価しない近似）。
  html = html.replace(/<!--\s*(BEGIN|ELSE|END)[\s\S]*?-->/g, '');

  // {id} はユニットIDのプレースホルダ。後続の汎用 {variable} 解決より先に固定する。
  html = html.replaceAll('{id}', id);

  // %{XXX} 形式のグローバル変数（%{ARCHIVES_DIR} 等）は空文字に解決する。
  html = html.replace(/%\{[A-Za-z0-9_]+\}/g, '');

  // 残りの {variable} / {variable@sub} / {variable:filter#arg} は、呼び出し側で指定された値が
  // あればそれを使い、なければ空文字に解決する。
  html = html.replace(/\{([^{}]+)\}/g, (_match, expression: string) => {
    const key = expression.split(/[:@]/)[0];
    return values[key] ?? '';
  });

  return html;
}
