#!/usr/bin/env bash

# Deploy the current Next.js standalone frontend to VMID 5000.
# This is the canonical deployment path for the current DBIS Explorer frontend.
# It builds the local frontend, uploads the standalone bundle, installs a systemd
# service, and starts the Node server on 127.0.0.1:3000 inside the container.

set -euo pipefail

VMID="${VMID:-5000}"
FRONTEND_PORT="${FRONTEND_PORT:-3000}"
FORCE_REMOTE_PCT="${FORCE_REMOTE_PCT:-0}"
SERVICE_NAME="solacescanscout-frontend"
APP_ROOT="/opt/solacescanscout/frontend"
PROXMOX_R630_02="${PROXMOX_HOST_R630_02:-192.168.11.12}"
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
WORKSPACE_ROOT="$(cd "$REPO_ROOT/.." && pwd)"
FRONTEND_ROOT="${REPO_ROOT}/frontend"
SERVICE_TEMPLATE="${REPO_ROOT}/deployment/systemd/solacescanscout-frontend.service"
NGINX_SNIPPET="${REPO_ROOT}/deployment/common/nginx-next-frontend-proxy.conf"
VERIFY_SCRIPT="${WORKSPACE_ROOT}/scripts/verify/check-explorer-e2e.sh"
RELEASE_ID="$(date +%Y%m%d_%H%M%S)"
TMP_DIR="$(mktemp -d)"
ARCHIVE_NAME="solacescanscout-next-${RELEASE_ID}.tar"
BUILD_LOCK_DIR="${FRONTEND_ROOT}/.next-build-lock"
STANDALONE_ROOT="${FRONTEND_ROOT}/.next/standalone"
STATIC_SYNC_FILES=(
  "index.html"
  "docs.html"
  "privacy.html"
  "terms.html"
  "acknowledgments.html"
  "chain138-command-center.html"
  "favicon.ico"
  "apple-touch-icon.png"
  "explorer-spa.js"
)

cleanup() {
  if [[ -d "$BUILD_LOCK_DIR" ]]; then
    rmdir "$BUILD_LOCK_DIR" 2>/dev/null || true
  fi
  rm -rf "$TMP_DIR"
}
trap cleanup EXIT

if [[ ! -f "$SERVICE_TEMPLATE" ]]; then
  echo "Missing service template: $SERVICE_TEMPLATE" >&2
  exit 1
fi

push_into_vmid() {
  local source_path="$1"
  local destination_path="$2"
  local perms="${3:-0644}"

  if [[ "$FORCE_REMOTE_PCT" != "1" ]] && [[ -f /proc/1/cgroup ]] && grep -q "lxc" /proc/1/cgroup 2>/dev/null; then
    install -D -m "$perms" "$source_path" "$destination_path"
  elif command -v pct >/dev/null 2>&1; then
    pct push "$VMID" "$source_path" "$destination_path" --perms "$perms"
  else
    local remote_tmp="/tmp/$(basename "$source_path").$$"
    scp -o ConnectTimeout=10 -o StrictHostKeyChecking=no "$source_path" "root@${PROXMOX_R630_02}:${remote_tmp}"
    ssh -o ConnectTimeout=10 -o StrictHostKeyChecking=no "root@${PROXMOX_R630_02}" \
      "pct push ${VMID} ${remote_tmp} ${destination_path} --perms ${perms} && rm -f ${remote_tmp}"
  fi
}

run_in_vmid() {
  local command="$1"

  if [[ "$FORCE_REMOTE_PCT" != "1" ]] && [[ -f /proc/1/cgroup ]] && grep -q "lxc" /proc/1/cgroup 2>/dev/null; then
    bash -lc "$command"
  elif command -v pct >/dev/null 2>&1; then
    pct exec "$VMID" -- bash -lc "$command"
  else
    ssh -o ConnectTimeout=10 -o StrictHostKeyChecking=no "root@${PROXMOX_R630_02}" \
      "pct exec ${VMID} -- bash -lc $(printf '%q' "$command")"
  fi
}

echo "=========================================="
echo "Deploying Next DBIS Explorer Frontend"
echo "=========================================="
echo "VMID: $VMID"
echo "Frontend root: $FRONTEND_ROOT"
echo "Release: $RELEASE_ID"
echo ""

acquire_build_lock() {
  local attempts=0
  until mkdir "$BUILD_LOCK_DIR" 2>/dev/null; do
    attempts=$((attempts + 1))
    if (( attempts == 1 )); then
      echo "Waiting for another frontend build to finish..."
    fi
    if (( attempts >= 120 )); then
      echo "Timed out waiting for frontend build lock: $BUILD_LOCK_DIR" >&2
      exit 1
    fi
    sleep 1
  done
}

if [[ "${SKIP_BUILD:-0}" != "1" ]]; then
  echo "== Building frontend =="
  acquire_build_lock
  rm -rf "${FRONTEND_ROOT}/.next"
  (cd "$FRONTEND_ROOT" && npm run build)
  echo ""
fi

APP_RELATIVE_DIR="."
APP_SERVER_PATH="${STANDALONE_ROOT}/server.js"
if [[ ! -f "${APP_SERVER_PATH}" ]]; then
  ALT_SERVER_PATH="$(find "${STANDALONE_ROOT}" \
    -path '*/node_modules' -prune -o \
    -path '*/server.js' -print | head -n 1 || true)"
  if [[ -n "${ALT_SERVER_PATH}" ]]; then
    APP_SERVER_PATH="${ALT_SERVER_PATH}"
    APP_RELATIVE_DIR="$(dirname "${ALT_SERVER_PATH#${STANDALONE_ROOT}/}")"
  fi
fi

if [[ ! -f "${APP_SERVER_PATH}" ]]; then
  echo "Missing standalone server build. Run \`npm run build\` in ${FRONTEND_ROOT} first." >&2
  exit 1
fi

STAGE_DIR="${TMP_DIR}/stage"
APP_STAGE_DIR="${STAGE_DIR}"
if [[ "${APP_RELATIVE_DIR}" != "." ]]; then
  APP_STAGE_DIR="${STAGE_DIR}/${APP_RELATIVE_DIR}"
fi

mkdir -p "${APP_STAGE_DIR}/.next"
cp -R "${STANDALONE_ROOT}/." "$STAGE_DIR/"
cp -R "${FRONTEND_ROOT}/.next/static" "${APP_STAGE_DIR}/.next/static"
cp -R "${FRONTEND_ROOT}/public" "${APP_STAGE_DIR}/public"
tar -C "$STAGE_DIR" -cf "${TMP_DIR}/${ARCHIVE_NAME}" .

cp "$SERVICE_TEMPLATE" "${TMP_DIR}/${SERVICE_NAME}.service"
sed -i "s|/opt/solacescanscout/frontend/current|${APP_ROOT}/current|g" "${TMP_DIR}/${SERVICE_NAME}.service"
sed -i "s|Environment=PORT=3000|Environment=PORT=${FRONTEND_PORT}|g" "${TMP_DIR}/${SERVICE_NAME}.service"
if [[ "${APP_RELATIVE_DIR}" != "." ]]; then
  sed -i "s|WorkingDirectory=${APP_ROOT}/current|WorkingDirectory=${APP_ROOT}/current/${APP_RELATIVE_DIR}|g" "${TMP_DIR}/${SERVICE_NAME}.service"
  sed -i "s|ExecStart=/usr/bin/node ${APP_ROOT}/current/server.js|ExecStart=/usr/bin/node ${APP_ROOT}/current/${APP_RELATIVE_DIR}/server.js|g" "${TMP_DIR}/${SERVICE_NAME}.service"
fi

cat > "${TMP_DIR}/install-next-frontend.sh" <<EOF
#!/usr/bin/env bash
set -euo pipefail

APP_ROOT="${APP_ROOT}"
RELEASE_DIR="\${APP_ROOT}/releases/${RELEASE_ID}"
SERVICE_NAME="${SERVICE_NAME}"
FRONTEND_PORT="${FRONTEND_PORT}"

mkdir -p "\${APP_ROOT}/releases"
mkdir -p "\${RELEASE_DIR}"
tar -xf "/tmp/${ARCHIVE_NAME}" -C "\${RELEASE_DIR}"
ln -sfn "\${RELEASE_DIR}" "\${APP_ROOT}/current"
chown -R www-data:www-data "\${APP_ROOT}"

install -m 0644 "/tmp/${SERVICE_NAME}.service" "/etc/systemd/system/\${SERVICE_NAME}.service"
systemctl daemon-reload
systemctl enable "\${SERVICE_NAME}.service" >/dev/null
systemctl restart "\${SERVICE_NAME}.service"

for attempt in \$(seq 1 45); do
  if curl -fsS --max-time 5 "http://127.0.0.1:\${FRONTEND_PORT}/" > /tmp/\${SERVICE_NAME}-health.out; then
    break
  fi
  sleep 1
done

if ! grep -qiE "DBIS Explorer|Chain 138 Explorer by DBIS" /tmp/\${SERVICE_NAME}-health.out; then
  systemctl status "\${SERVICE_NAME}.service" --no-pager || true
  journalctl -u "\${SERVICE_NAME}.service" -n 50 --no-pager || true
  echo "Frontend health check did not find the expected DBIS Explorer marker." >&2
  exit 1
fi

mkdir -p /var/www/html
for relpath in ${STATIC_SYNC_FILES[*]}; do
  if [[ -f "\${RELEASE_DIR}/public/\${relpath}" ]]; then
    install -D -m 0644 "\${RELEASE_DIR}/public/\${relpath}" "/var/www/html/\${relpath}"
  fi
done
if [[ -d "\${RELEASE_DIR}/public/thirdparty" ]]; then
  mkdir -p /var/www/html/thirdparty
  cp -a "\${RELEASE_DIR}/public/thirdparty/." /var/www/html/thirdparty/
fi
if [[ -d "\${RELEASE_DIR}/public/config" ]]; then
  mkdir -p /var/www/html/config
  cp -a "\${RELEASE_DIR}/public/config/." /var/www/html/config/
fi
EOF
chmod +x "${TMP_DIR}/install-next-frontend.sh"

echo "== Uploading release bundle =="
push_into_vmid "${TMP_DIR}/${ARCHIVE_NAME}" "/tmp/${ARCHIVE_NAME}" 0644
push_into_vmid "${TMP_DIR}/${SERVICE_NAME}.service" "/tmp/${SERVICE_NAME}.service" 0644
push_into_vmid "${TMP_DIR}/install-next-frontend.sh" "/tmp/install-next-frontend.sh" 0755
echo ""

echo "== Installing release and restarting service =="
run_in_vmid "/tmp/install-next-frontend.sh"
echo ""

echo "== Verification =="
run_in_vmid "systemctl is-active ${SERVICE_NAME}.service"
run_in_vmid "curl -fsS --max-time 5 http://127.0.0.1:${FRONTEND_PORT}/ | grep -qiE 'DBIS Explorer|Chain 138 Explorer by DBIS'"
echo "Service ${SERVICE_NAME} is running on 127.0.0.1:${FRONTEND_PORT}"
echo ""
echo "Nginx follow-up:"
echo "  Switch the explorer server block to proxy / and /_next/ to 127.0.0.1:${FRONTEND_PORT}"
echo "  while preserving /api/, /api/config/*, /explorer-api/v1/, /token-aggregation/api/v1/, /snap/, and /health."
echo "  Snippet: ${NGINX_SNIPPET}"
if [[ -f "${VERIFY_SCRIPT}" ]]; then
  echo "  After nginx/NPMplus cutover, verify with:"
  echo "    bash ${VERIFY_SCRIPT} https://blockscout.defi-oracle.io"
fi
echo ""
echo "Next frontend deployment complete."
