#!/usr/bin/env bash
# Stage dist/release/ for Windows USB install (bundled node_modules — offline install on client).
set -euo pipefail

ROOT="$(cd "$(dirname "$0")/../.." && pwd)"
VERSION="${1:-$(node -p "require('${ROOT}/package.json').version")}"
NODE_VER="20.19.5"
ARCH="win-x64"
NODE_ZIP="node-v${NODE_VER}-win-x64.zip"
NODE_URL="https://nodejs.org/dist/v${NODE_VER}/${NODE_ZIP}"

RELEASE="${ROOT}/dist/release"
PAYLOAD="${RELEASE}/payload/${ARCH}"
APP="${PAYLOAD}/app"
RUNTIME="${PAYLOAD}/runtime"
TMP="$(mktemp -d)"

cleanup() { rm -rf "$TMP"; }
trap cleanup EXIT

echo "==> Staging Windows USB release v${VERSION}"

rm -rf "${RELEASE}/payload/${ARCH}"
mkdir -p "$APP" "$RUNTIME"

rsync -a \
  --exclude='.git' \
  --exclude='node_modules' \
  --exclude='dist' \
  --exclude='.env' \
  --exclude='printer.js.backup' \
  "$ROOT/" "$APP/"

echo "==> Installing npm dependencies into staged app (offline client install)..."
(
  cd "$APP"
  if [[ -d "${ROOT}/node_modules" ]]; then
    npm ci --omit=dev
  else
    (cd "$ROOT" && npm ci --omit=dev)
    rsync -a "${ROOT}/node_modules/" "${APP}/node_modules/"
  fi
)

echo "==> Syncing staged app version to ${VERSION}..."
node -e "
const fs = require('fs');
const v = '${VERSION}';
const app = '${APP}';
for (const name of ['package.json', 'package-lock.json']) {
  const p = require('path').join(app, name);
  if (!fs.existsSync(p)) continue;
  const j = JSON.parse(fs.readFileSync(p, 'utf8'));
  j.version = v;
  if (name === 'package-lock.json' && j.packages && j.packages['']) {
    j.packages[''].version = v;
  }
  fs.writeFileSync(p, JSON.stringify(j, null, 2) + '\n');
}
"

if [[ ! -f "${APP}/node_modules/node-windows/package.json" ]]; then
  echo "ERROR: node_modules/node-windows missing after npm ci" >&2
  exit 1
fi

echo "==> Downloading Node ${NODE_VER} for Windows (${ARCH})…"
curl -fsSL "$NODE_URL" -o "${TMP}/${NODE_ZIP}"
unzip -q "${TMP}/${NODE_ZIP}" -d "$TMP"
NODE_DIR="$(find "$TMP" -maxdepth 1 -type d -name 'node-v*-win-x64' | head -1)"
if [[ -z "$NODE_DIR" || ! -f "${NODE_DIR}/node.exe" ]]; then
  echo "ERROR: node.exe not found in ${NODE_ZIP}" >&2
  exit 1
fi
cp -a "${NODE_DIR}/." "$RUNTIME/"

cp -f "${ROOT}/installer/windows/Install.cmd" "${RELEASE}/Install.cmd"
cp -f "${ROOT}/installer/windows/Update.cmd" "${RELEASE}/Update.cmd"
cp -f "${ROOT}/installer/windows/Repair.cmd" "${RELEASE}/Repair.cmd"
cp -f "${ROOT}/installer/windows/Open-Setup.cmd" "${RELEASE}/Open-Setup.cmd"
cp -f "${ROOT}/installer/windows/STOP-AGENT.cmd" "${RELEASE}/STOP-AGENT.cmd"
cp -f "${ROOT}/installer/windows/start-agent.bat" "${RELEASE}/start-agent.bat"
cp -f "${ROOT}/installer/windows/install-service.js" "${RELEASE}/install-service.js"
cp -f "${ROOT}/installer/windows/uninstall-service.js" "${RELEASE}/uninstall-service.js"
# UTF-8 BOM helps Windows PowerShell 5.1 parse install scripts reliably.
{
  printf '\xEF\xBB\xBF'
  cat "${ROOT}/installer/windows/install-from-folder.ps1"
} > "${RELEASE}/install-from-folder.ps1"
{
  printf '\xEF\xBB\xBF'
  cat "${ROOT}/installer/windows/repair-from-folder.ps1"
} > "${RELEASE}/repair-from-folder.ps1"
cp -f "${ROOT}/installer/windows/stop-agent.ps1" "${RELEASE}/stop-agent.ps1"
cp -f "${ROOT}/installer/windows/install-repair-cycle.ps1" "${RELEASE}/install-repair-cycle.ps1"
cp -f "${ROOT}/installer/windows/health-probe.js" "${RELEASE}/health-probe.js"
cp -f "${ROOT}/installer/windows/sync-apply.js" "${RELEASE}/sync-apply.js"

if [[ -f "${ROOT}/dist/release/Sync.exe" ]]; then
  cp -f "${ROOT}/dist/release/Sync.exe" "${RELEASE}/Sync.exe"
elif [[ -f "${ROOT}/scripts/build-sync-exe.sh" ]]; then
  bash "${ROOT}/scripts/build-sync-exe.sh" || echo "WARN: Sync.exe not built"
  if [[ -f "${ROOT}/dist/release/Sync.exe" ]]; then
    cp -f "${ROOT}/dist/release/Sync.exe" "${RELEASE}/Sync.exe"
  fi
fi

cp -f "${ROOT}/COPY_TO_WINDOWS.txt" "${RELEASE}/COPY_TO_WINDOWS.txt"
cp -f "${ROOT}/installer/linux/USB-START-HERE.txt" "${RELEASE}/START_HERE.txt"

for required in \
  "${RELEASE}/Install.cmd" \
  "${RELEASE}/Repair.cmd" \
  "${RELEASE}/Update.cmd" \
  "${RELEASE}/start-agent.bat" \
  "${RELEASE}/install-service.js" \
  "${RELEASE}/uninstall-service.js" \
  "${RELEASE}/install-from-folder.ps1" \
  "${RELEASE}/repair-from-folder.ps1" \
  "${APP}/index.js" \
  "${APP}/node_modules/node-windows/package.json" \
  "${APP}/installer/windows/install-service.js" \
  "${RUNTIME}/node.exe"; do
  if [[ ! -f "$required" ]]; then
    echo "ERROR: staged release missing required file: $required" >&2
    exit 1
  fi
done

if ! grep -q "manualSpoolerName" "${APP}/index.js"; then
  echo "ERROR: staged index.js missing manual printer UI (manualSpoolerName)" >&2
  exit 1
fi

cat > "${RELEASE}/manifest.json" <<EOF
{
  "version": "${VERSION}",
  "arch": "${ARCH}",
  "builtAt": "$(date -u +%Y-%m-%dT%H:%M:%SZ)",
  "entry": { "windows": "Install.cmd" },
  "payload": "payload/${ARCH}",
  "installTarget": "%ProgramFiles%\\\\Siraya\\\\Printer",
  "uiUrl": "http://127.0.0.1:5000"
}
EOF

cat > "${PAYLOAD}/payload-manifest.json" <<EOF
{
  "version": "${VERSION}",
  "arch": "${ARCH}",
  "nodeVersion": "${NODE_VER}",
  "builtAt": "$(date -u +%Y-%m-%dT%H:%M:%SZ)"
}
EOF

SIZE="$(du -sh "$RELEASE" | cut -f1)"
echo ""
echo "Done: ${RELEASE} (${SIZE})"
echo "Copy the entire dist/release/ folder to your USB, then on Windows 10 open Install.cmd"
