#!/bin/sh
set -eu

CONTAINER="${1:-reactive-resume-reactive-resume-1}"

docker exec -u root -i "$CONTAINER" sh <<'SH'
set -eu

SSR_FILE="/app/apps/web/.output/server/_ssr/pdf-document-COfeOLVC.mjs"
PUBLIC_FILE="/app/apps/web/.output/public/assets/pdf-document-BplbXx-0.js"
SERVER_INDEX_FILE="/app/apps/web/.output/server/index.mjs"
CACHE_BUST="rr-glalie-layout-20260518"

test -f "$SSR_FILE.bak-glalie-layout" || cp "$SSR_FILE" "$SSR_FILE.bak-glalie-layout" 2>/dev/null || true
test -f "$PUBLIC_FILE.bak-glalie-layout" || cp "$PUBLIC_FILE" "$PUBLIC_FILE.bak-glalie-layout" 2>/dev/null || true
test -f "$SERVER_INDEX_FILE.bak-glalie-layout" || cp "$SERVER_INDEX_FILE" "$SERVER_INDEX_FILE.bak-glalie-layout" 2>/dev/null || true

node - <<'NODE'
const fs = require("fs");
const crypto = require("crypto");

const ssrFile = "/app/apps/web/.output/server/_ssr/pdf-document-COfeOLVC.mjs";
const publicFile = "/app/apps/web/.output/public/assets/pdf-document-BplbXx-0.js";
const serverIndexFile = "/app/apps/web/.output/server/index.mjs";
const cacheBust = "rr-glalie-layout-20260518";

function replaceOnce(source, from, to, label) {
  if (source.includes(to)) return source;
  if (!source.includes(from)) throw new Error(`Patch marker not found: ${label}`);
  return source.replace(from, to);
}

function replaceRegexOnce(source, regex, to, label) {
  if (source.includes(to)) return source;
  const next = source.replace(regex, to);
  if (next === source) throw new Error(`Patch marker not found: ${label}`);
  return next;
}

function patchSsr(source) {
  source = source
    .replace(/const sideMargin = bodyLineHeight \* \.(?:2|08);/, "const sideMargin = bodyLineHeight * .08;")
    .replace(/metrics\.gapY\(3\.5\)/g, "metrics.gapY(3.0)")
    .replace(/metrics\.gapY\(2\.6\)/g, "metrics.gapY(3.0)")
    .replace(/metrics\.gapY\(2\.2\)/g, "metrics.gapY(3.0)");

  source = source
    .replace(
      /style: composeStyles\(styles\.sidebarContent, \{ rowGap: metrics\.sectionGap \}\),/g,
      "style: composeStyles(styles.sidebarContent, { rowGap: metrics.gapY(2.2) }),",
    )
    .replace(
      /style: composeStyles\(styles\.mainContent, \{ rowGap: metrics\.sectionGap \}\),/g,
      "style: composeStyles(styles.mainContent, { rowGap: metrics.gapY(2.2) }),",
    );
  source = source.replace(
    /sectionHeading: \{\s*borderBottomWidth: 1,\s*borderBottomColor: primary(?:,\s*paddingBottom: 1(?:\.3)?)?\s*\},/,
    `sectionHeading: {
\t\t\t\t\tborderBottomWidth: 1,
\t\t\t\t\tborderBottomColor: primary,
\t\t\t\t\tpaddingBottom: 1.3
\t\t\t\t},`,
  );
  source = replaceRegexOnce(
    source,
    /sectionHeading: \{\s*borderBottomWidth: 1,\s*borderBottomColor: primary,\s*paddingBottom: 1(?:\.3)?\s*\},\s*item: \{ rowGap: metrics\.gapY\(\.125\) \},/,
    `sectionHeading: {
\t\t\t\t\tborderBottomWidth: 1,
\t\t\t\t\tborderBottomColor: primary,
\t\t\t\t\tpaddingBottom: 1.3
\t\t\t\t},
\t\t\t\tsectionItems: { paddingTop: metrics.gapY(.55) },
\t\t\t\titem: { rowGap: metrics.gapY(.2) },`,
    "SSR Glalie section item spacing",
  );
  source = replaceRegexOnce(
    source,
    /sidebarColumn: \{\s*zIndex: 1,\s*backgroundColor: primaryTint,\s*paddingHorizontal: metrics\.page\.paddingHorizontal,\s*paddingTop: metrics\.page\.paddingVertical,\s*(?:paddingBottom: metrics\.page\.paddingVertical,\s*)?rowGap: (?:metrics\.sectionGap|metrics\.gapY\([^)]+\))\s*\},/,
    `sidebarColumn: {
\t\t\t\t\tzIndex: 1,
\t\t\t\t\tbackgroundColor: primaryTint,
\t\t\t\t\tpaddingHorizontal: metrics.page.paddingHorizontal,
\t\t\t\t\tpaddingTop: metrics.page.paddingVertical,
\t\t\t\t\tpaddingBottom: metrics.page.paddingVertical,
\t\t\t\t\trowGap: metrics.gapY(3.0)
\t\t\t\t},`,
    "SSR Glalie sidebar bottom padding",
  );
  source = replaceRegexOnce(
    source,
    /mainContent: \{\s*paddingHorizontal: metrics\.page\.paddingHorizontal,\s*paddingTop: metrics\.page\.paddingVertical,\s*(?:paddingBottom: metrics\.page\.paddingVertical\s*)?\},/,
    `mainContent: {
\t\t\t\t\tpaddingHorizontal: metrics.page.paddingHorizontal,
\t\t\t\t\tpaddingTop: metrics.page.paddingVertical,
\t\t\t\t\tpaddingBottom: metrics.page.paddingVertical
\t\t\t\t},`,
    "SSR Glalie main bottom padding",
  );
  return source
    .replace(/const sideMargin = bodyLineHeight \* \.(?:2|08);/, "const sideMargin = bodyLineHeight * .08;")
    .replace(/metrics\.gapY\(3\.5\)/g, "metrics.gapY(3.0)")
    .replace(/metrics\.gapY\(2\.6\)/g, "metrics.gapY(3.0)")
    .replace(/metrics\.gapY\(2\.2\)/g, "metrics.gapY(3.0)");
}

function patchPublic(source) {
  source = source
    .replace(/([A-Za-z_$][\w$]*)=([A-Za-z_$][\w$]*)\*\.(?:2|08);return\{paragraph:\{marginTop:\1,marginBottom:\1\},listItem:\{marginTop:\1,marginBottom:\1\}\}/,
      "$1=$2*.08;return{paragraph:{marginTop:$1,marginBottom:$1},listItem:{marginTop:$1,marginBottom:$1}}")
    .replace(/o\.gapY\(3\.5\)/g, "o.gapY(3.0)")
    .replace(/c\.gapY\(3\.5\)/g, "c.gapY(3.0)")
    .replace(/o\.gapY\(2\.6\)/g, "o.gapY(3.0)")
    .replace(/c\.gapY\(2\.6\)/g, "c.gapY(3.0)")
    .replace(/o\.gapY\(2\.2\)/g, "o.gapY(3.0)")
    .replace(/c\.gapY\(2\.2\)/g, "c.gapY(3.0)");

  source = source
    .replace(/style:\$\(a\.sidebarContent,\{rowGap:o\.sectionGap\}\)/g, "style:$(a.sidebarContent,{rowGap:o.gapY(3.0)})")
    .replace(/style:\$\(a\.mainContent,\{rowGap:o\.sectionGap\}\)/g, "style:$(a.mainContent,{rowGap:o.gapY(3.0)})");
  source = source.replace(
    /sectionHeading:\{borderBottomWidth:1,borderBottomColor:a(?:,paddingBottom:1(?:\.3)?)?\}/,
    "sectionHeading:{borderBottomWidth:1,borderBottomColor:a,paddingBottom:1.3}",
  );
  source = source.replace(
    /sectionHeading:\{borderBottomWidth:1,borderBottomColor:a,paddingBottom:1(?:\.3)?\},item:\{rowGap:([a-zA-Z_$][\w$]*)\.gapY\(\.125\)\}/,
    "sectionHeading:{borderBottomWidth:1,borderBottomColor:a,paddingBottom:1.3},sectionItems:{paddingTop:$1.gapY(.55)},item:{rowGap:$1.gapY(.2)}",
  );
  source = replaceOnce(
    source,
    "sidebarColumn:{zIndex:1,backgroundColor:o,paddingHorizontal:c.page.paddingHorizontal,paddingTop:c.page.paddingVertical,rowGap:c.sectionGap}",
    "sidebarColumn:{zIndex:1,backgroundColor:o,paddingHorizontal:c.page.paddingHorizontal,paddingTop:c.page.paddingVertical,paddingBottom:c.page.paddingVertical,rowGap:c.gapY(3.0)}",
    "public Glalie sidebar bottom padding",
  );
  source = replaceOnce(
    source,
    "mainContent:{paddingHorizontal:c.page.paddingHorizontal,paddingTop:c.page.paddingVertical}",
    "mainContent:{paddingHorizontal:c.page.paddingHorizontal,paddingTop:c.page.paddingVertical,paddingBottom:c.page.paddingVertical}",
    "public Glalie main bottom padding",
  );
  return source
    .replace(/([A-Za-z_$][\w$]*)=([A-Za-z_$][\w$]*)\*\.(?:2|08);return\{paragraph:\{marginTop:\1,marginBottom:\1\},listItem:\{marginTop:\1,marginBottom:\1\}\}/,
      "$1=$2*.08;return{paragraph:{marginTop:$1,marginBottom:$1},listItem:{marginTop:$1,marginBottom:$1}}")
    .replace(/o\.gapY\(3\.5\)/g, "o.gapY(3.0)")
    .replace(/c\.gapY\(3\.5\)/g, "c.gapY(3.0)")
    .replace(/o\.gapY\(2\.6\)/g, "o.gapY(3.0)")
    .replace(/c\.gapY\(2\.6\)/g, "c.gapY(3.0)")
    .replace(/o\.gapY\(2\.2\)/g, "o.gapY(3.0)")
    .replace(/c\.gapY\(2\.2\)/g, "c.gapY(3.0)");
}

function patchImporters() {
  const assetsDir = "/app/apps/web/.output/public/assets";
  const files = fs
    .readdirSync(assetsDir)
    .filter((name) => name.endsWith(".js"))
    .map((name) => `${assetsDir}/${name}`)
    .filter((file) => fs.readFileSync(file, "utf8").includes("pdf-document-BplbXx-0.js"));

  for (const file of files) {
    let source = fs.readFileSync(file, "utf8");
    source = source.replace(/\.\/pdf-document-BplbXx-0\.js(?:\?v=rr-glalie-layout-20260518)?/g, `./pdf-document-BplbXx-0.js?v=${cacheBust}`);
    fs.writeFileSync(file, source);
  }

  return files;
}

function makeEtag(buffer) {
  const digest = crypto.createHash("sha1").update(buffer).digest("base64").replace(/=+$/g, "");
  return `"${buffer.length.toString(16)}-${digest}"`;
}

function patchStaticManifestEntry(source, urlPath, filePath) {
  const buffer = fs.readFileSync(filePath);
  const startMarker = `"${urlPath}": {`;
  const start = source.indexOf(startMarker);
  if (start === -1) throw new Error(`Static manifest entry not found for ${urlPath}`);

  const commaEnd = source.indexOf("\n\t},", start);
  const objectEnd = source.indexOf("\n\t}", start);
  const end = commaEnd === -1 ? objectEnd : Math.min(commaEnd, objectEnd);
  if (end === -1) throw new Error(`Static manifest entry end not found for ${urlPath}`);

  let entry = source.slice(start, end);
  entry = entry
    .replace(/"etag": "(?:\\.|[^"\\])*"/, `"etag": ${JSON.stringify(makeEtag(buffer))}`)
    .replace(/"mtime": "(?:\\.|[^"\\])*"/, `"mtime": ${JSON.stringify(new Date().toISOString())}`)
    .replace(/"size": \d+/, `"size": ${buffer.length}`);

  return source.slice(0, start) + entry + source.slice(end);
}

fs.writeFileSync(ssrFile, patchSsr(fs.readFileSync(ssrFile, "utf8")));
fs.writeFileSync(publicFile, patchPublic(fs.readFileSync(publicFile, "utf8")));

const importers = patchImporters();
let serverIndex = fs.readFileSync(serverIndexFile, "utf8");
serverIndex = patchStaticManifestEntry(serverIndex, "/assets/pdf-document-BplbXx-0.js", publicFile);
for (const file of importers) {
  const urlPath = `/assets/${file.split("/").pop()}`;
  serverIndex = patchStaticManifestEntry(serverIndex, urlPath, file);
}
fs.writeFileSync(serverIndexFile, serverIndex);
NODE

node --check "$SSR_FILE" >/dev/null
node --check "$PUBLIC_FILE" >/dev/null
node --check "$SERVER_INDEX_FILE" >/dev/null
SH
