#!/bin/sh
# DSM 7 lifecycle script.  Package Center invokes this as the package user,
# never as root.  Persistent state belongs in SYNOPKG_PKGVAR, not target.

PACKAGE_NAME="${SYNOPKG_PKGNAME:-FCEmulatorLibrary}"
PACKAGE_DEST="${SYNOPKG_PKGDEST:-/var/packages/${PACKAGE_NAME}/target}"
PACKAGE_VAR="${SYNOPKG_PKGVAR:-/var/packages/${PACKAGE_NAME}/var}"
APP_DIR="${PACKAGE_DEST}/app"
PID_FILE="${PACKAGE_VAR}/fc-emulator-library.pid"
LOG_FILE="${PACKAGE_VAR}/fc-emulator-library.log"
PORT="${FC_LIBRARY_PORT:-8282}"
HOST="${FC_LIBRARY_HOST:-0.0.0.0}"
TEST_INSTANCE=0
if [ -f "${PACKAGE_DEST}/test-instance" ]; then
  # A differently named DSM package gives this instance its own account,
  # lifecycle and var directory.  Refuse a misplaced marker rather than
  # accidentally starting the test service inside the production package.
  if [ "${PACKAGE_NAME}" != "FCEmulatorLibraryTest" ]; then
    echo "测试实例必须以 FCEmulatorLibraryTest 套件运行。" >&2
    exit 1
  fi
  TEST_INSTANCE=1
  PORT=8383
fi

resolve_node() {
  for candidate in \
    "${FC_LIBRARY_NODE_BIN:-}" \
    "${PACKAGE_DEST}/runtime/node" \
    "/var/packages/Node.js_v22/target/usr/local/bin/node" \
    "/var/packages/Node.js_v20/target/usr/local/bin/node" \
    "/var/packages/Node.js_v18/target/usr/local/bin/node" \
    "/var/packages/nodejs_v22/target/bin/node" \
    "/var/packages/nodejs_v20/target/bin/node" \
    "/var/packages/nodejs_v18/target/bin/node"; do
    if [ -n "${candidate}" ] && [ -x "${candidate}" ]; then
      echo "${candidate}"
      return 0
    fi
  done
  if command -v node >/dev/null 2>&1; then command -v node; return 0; fi
  return 1
}

check_node() {
  NODE_BIN="$(resolve_node)" || {
    echo "未找到 Node.js 18+。请安装 Synology Node.js 套件，或使用 build-public-spk.sh --node-bin 打入与 NAS 架构匹配的 Node。" >&2
    return 1
  }
  "${NODE_BIN}" -e 'process.exit(Number(process.versions.node.split(".")[0]) >= 18 ? 0 : 1)' || {
    echo "Node.js 版本过低：需要 Node.js 18 或更高版本。" >&2
    return 1
  }
}

is_running() {
  [ -s "${PID_FILE}" ] || return 1
  pid="$(cat "${PID_FILE}" 2>/dev/null)"
  [ -n "${pid}" ] && kill -0 "${pid}" 2>/dev/null
}

case "$1" in
  prestart)
    check_node
    ;;
  start)
    if is_running; then exit 0; fi
    check_node || exit 1
    mkdir -p "${PACKAGE_VAR}"
    NODE_BIN="$(resolve_node)"
    if [ "${TEST_INSTANCE}" = 1 ]; then
      mkdir -p "${PACKAGE_VAR}/data" "${PACKAGE_VAR}/test-library" "${PACKAGE_VAR}/keys" || exit 1
      # This is a public portable-library index, not the private catalog in
      # PACKAGE_VAR.  Exclusive creation preserves test games across upgrades.
      "${NODE_BIN}" -e '
        const fs = require("node:fs");
        const target = process.argv[1];
        const timestamp = new Date().toISOString();
        let fd;
        try {
          fd = fs.openSync(target, "wx", 0o644);
        } catch (error) {
          if (error.code === "EEXIST") process.exit(0);
          throw error;
        }
        try {
          fs.writeFileSync(fd, JSON.stringify({
            schemaVersion: 1, title: "Retro Console Library 测试版",
            createdAt: timestamp, updatedAt: timestamp, games: []
          }, null, 2) + "\n");
        } finally {
          fs.closeSync(fd);
        }
      ' "${PACKAGE_VAR}/test-library/library.json" || exit 1
      (
        # Do not reuse production credentials, keys or source paths supplied
        # by an administrator's shell or the production package environment.
        unset DEEPSEEK_API_KEY DEEPSEEK_RESPONSES_BASE_URL FC_LIBRARY_TOKEN \
          FC_LIBRARY_PROTECT_LIBRARY FC_ATARI_KNOWN_CARTS FC_PGM_ROM_ROOT
        export FC_LIBRARY_DATA_DIR="${PACKAGE_VAR}/data"
        export FC_LIBRARY_SOURCE_DIRECTORY="${PACKAGE_VAR}/test-library"
        export FC_LIBRARY_CPS2_KEYS="${PACKAGE_VAR}/keys/cps2-keys.json"
        export FC_LIBRARY_CPS3_KEYS="${PACKAGE_VAR}/keys/cps3-keys.json"
        export FC_LIBRARY_PORT="${PORT}" FC_LIBRARY_HOST="${HOST}"
        export FC_LIBRARY_AUTOMATIC_COVER_SCAN_VERSION=0 FC_LIBRARY_AUTOMATIC_RESEARCH=0
        export FC_LIBRARY_DIRECTORY_BROWSE_ROOT="${PACKAGE_VAR}/test-library"
        export FC_LIBRARY_DIRECTORY_BROWSE_VOLUMES_ONLY=no
        exec "${NODE_BIN}" "${APP_DIR}/server.js"
      ) >>"${LOG_FILE}" 2>&1 &
    else
      FC_LIBRARY_DATA_DIR="${PACKAGE_VAR}" \
      FC_LIBRARY_PORT="${PORT}" \
      FC_LIBRARY_HOST="${HOST}" \
      FC_LIBRARY_AUTOMATIC_COVER_SCAN_VERSION="90" \
      FC_LIBRARY_AUTOMATIC_RESEARCH="1" \
      FC_LIBRARY_DIRECTORY_BROWSE_ROOT="${FC_LIBRARY_DIRECTORY_BROWSE_ROOT:-/}" \
      FC_LIBRARY_DIRECTORY_BROWSE_VOLUMES_ONLY="${FC_LIBRARY_DIRECTORY_BROWSE_VOLUMES_ONLY:-yes}" \
      "${NODE_BIN}" "${APP_DIR}/server.js" >>"${LOG_FILE}" 2>&1 &
    fi
    echo $! >"${PID_FILE}"
    sleep 1
    if ! is_running; then
      rm -f "${PID_FILE}"
      echo "服务未能启动，请查看 ${LOG_FILE}。" >&2
      exit 1
    fi
    ;;
  prestop)
    exit 0
    ;;
  stop)
    if ! [ -s "${PID_FILE}" ]; then exit 0; fi
    pid="$(cat "${PID_FILE}" 2>/dev/null)"
    if [ -n "${pid}" ]; then
      kill "${pid}" 2>/dev/null || true
      attempt=0
      while kill -0 "${pid}" 2>/dev/null && [ "${attempt}" -lt 10 ]; do sleep 1; attempt=$((attempt + 1)); done
      kill -9 "${pid}" 2>/dev/null || true
    fi
    rm -f "${PID_FILE}"
    ;;
  status)
    if is_running; then exit 0; fi
    if [ -e "${PID_FILE}" ]; then exit 1; fi
    exit 3
    ;;
  *)
    exit 1
    ;;
esac

exit 0
