#!/usr/bin/env bash
# packaging/deploy-watchdog.sh — compile on laptop, deploy off-laptop watchdog binary to debian1.
# audience: AI agents. Fail-closed: any step failing exits non-zero with a JSON status line.
set -euo pipefail

ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
SSH_KEY="${HOME}/.ssh/id_ed25519_buildbox"
SSH_PORT="2222"
REMOTE_HOST="debian1"
DRY_RUN_ROOT="/tmp/overdeck-watchdog-dry-run"
TUNNEL_UNIT_NAME="overdeck-tunnel.service"
WATCHDOG_UNIT_NAME="overdeck-watchdog.service"

fail() {
  printf '{"stage":"deploy-watchdog","status":"error","detail":"%s"}\n' "$1" >&2
  exit 1
}

json_argv() {
  local type="$1"
  shift
  local -a quoted=()
  local part escaped
  for part in "$@"; do
    escaped="${part//\\/\\\\}"
    escaped="${escaped//\"/\\\"}"
    quoted+=("\"${escaped}\"")
  done
  local joined
  joined=$(IFS=,; printf '%s' "${quoted[*]}")
  printf '{"type":"%s","argv":[%s]}\n' "$type" "$joined"
}

render_tunnel_unit() {
  cat "${SCRIPT_DIR}/overdeck-tunnel.service"
}

render_watchdog_unit() {
  cat "${SCRIPT_DIR}/overdeck-watchdog.service"
}

print_dry_run_plan() {
  json_argv ssh-argv \
    ssh -N -T -p "${SSH_PORT}" -i "${SSH_KEY}" \
    -o ExitOnForwardFailure=yes \
    -o ServerAliveInterval=15 \
    -o ServerAliveCountMax=3 \
    -R 127.0.0.1:18787:127.0.0.1:8787 \
    -R 127.0.0.1:18138:127.0.0.1:31338 \
    "${REMOTE_HOST}"

  json_argv rsync-argv \
    rsync --archive --chmod=F755 \
    --rsh "ssh -p ${SSH_PORT} -i ${SSH_KEY}" \
    "${DRY_RUN_ROOT}/overdeck-watchdog" \
    "${REMOTE_HOST}:~/.local/bin/overdeck-watchdog"

  json_argv rsync-argv \
    rsync --archive --chmod=F644 \
    --rsh "ssh -p ${SSH_PORT} -i ${SSH_KEY}" \
    "${DRY_RUN_ROOT}/overdeck-watchdog.service" \
    "${REMOTE_HOST}:~/.config/systemd/user/overdeck-watchdog.service"

  printf 'unit:%s\n' "${TUNNEL_UNIT_NAME}"
  render_tunnel_unit
  printf 'unit:%s\n' "${WATCHDOG_UNIT_NAME}"
  render_watchdog_unit
}

if [[ "${OVERDECK_WATCHDOG_DEPLOY_DRY_RUN:-}" == "1" ]]; then
  print_dry_run_plan
  exit 0
fi

command -v bun >/dev/null 2>&1 || fail "bun-missing" "bun is not on PATH"
command -v rsync >/dev/null 2>&1 || fail "rsync-missing" "rsync is not on PATH"
command -v ssh >/dev/null 2>&1 || fail "ssh-missing" "ssh is not on PATH"
[[ -f "${SSH_KEY}" ]] || fail "ssh-key-missing" "SSH key not found at ${SSH_KEY}"

mkdir -p "${HOME}/.config/systemd/user"
cp "${SCRIPT_DIR}/overdeck-tunnel.service" "${HOME}/.config/systemd/user/${TUNNEL_UNIT_NAME}"
systemctl --user daemon-reload
systemctl --user enable --now "${TUNNEL_UNIT_NAME}" || fail "tunnel-start-failed" "failed to enable/start ${TUNNEL_UNIT_NAME}"

build_dir="$(mktemp -d)"
trap 'rm -rf "${build_dir}"' EXIT

bun build --compile --target=bun-linux-x64 \
  "${ROOT}/controller/src/watchdog-main.ts" \
  --outfile "${build_dir}/overdeck-watchdog" \
  || fail "compile-failed" "bun build --compile failed"

"${build_dir}/overdeck-watchdog" --help >/dev/null \
  || fail "help-failed" "compiled watchdog --help failed"

cp "${SCRIPT_DIR}/overdeck-watchdog.service" "${build_dir}/overdeck-watchdog.service"

ssh -p "${SSH_PORT}" -i "${SSH_KEY}" "${REMOTE_HOST}" \
  'mkdir -p ~/.local/bin ~/.config/systemd/user' \
  || fail "remote-mkdir-failed" "failed to create remote directories"

rsync --archive --chmod=F755 \
  --rsh "ssh -p ${SSH_PORT} -i ${SSH_KEY}" \
  "${build_dir}/overdeck-watchdog" \
  "${REMOTE_HOST}:~/.local/bin/overdeck-watchdog" \
  || fail "rsync-binary-failed" "failed to rsync watchdog binary"

rsync --archive --chmod=F644 \
  --rsh "ssh -p ${SSH_PORT} -i ${SSH_KEY}" \
  "${build_dir}/overdeck-watchdog.service" \
  "${REMOTE_HOST}:~/.config/systemd/user/overdeck-watchdog.service" \
  || fail "rsync-unit-failed" "failed to rsync watchdog unit"

remote_token_check="$(ssh -p "${SSH_PORT}" -i "${SSH_KEY}" "${REMOTE_HOST}" \
  'token="$HOME/.config/overdeck/token"; config="$HOME/.config/overdeck/watchdog.json"; for f in "$token" "$config"; do [ -f "$f" ] || { echo "missing:$f"; exit 1; }; mode=$(stat -c %a "$f"); [ "$mode" = "600" ] || { echo "mode:$f:$mode"; exit 1; }; done; echo ok' \
  2>&1 || true)"
[[ "${remote_token_check}" == "ok" ]] \
  || fail "remote-config-check-failed" "remote token/config missing or wrong mode: ${remote_token_check}"

ssh -p "${SSH_PORT}" -i "${SSH_KEY}" "${REMOTE_HOST}" \
  '~/.local/bin/overdeck-watchdog config-validate' \
  || fail "remote-config-validate-failed" "remote config-validate failed"

ssh -p "${SSH_PORT}" -i "${SSH_KEY}" "${REMOTE_HOST}" \
  'systemctl --user daemon-reload && systemctl --user enable --now overdeck-watchdog.service' \
  || fail "remote-unit-start-failed" "failed to enable/restart remote watchdog unit"

systemctl --user is-active --quiet "${TUNNEL_UNIT_NAME}" \
  || fail "tunnel-inactive" "local ${TUNNEL_UNIT_NAME} is not active"

remote_active="$(ssh -p "${SSH_PORT}" -i "${SSH_KEY}" "${REMOTE_HOST}" \
  'systemctl --user is-active overdeck-watchdog.service' 2>/dev/null || true)"
[[ "${remote_active}" == "active" ]] \
  || fail "watchdog-inactive" "remote ${WATCHDOG_UNIT_NAME} is not active"

printf '{"stage":"deploy-watchdog","status":"deployed","remote":"%s"}\n' "${REMOTE_HOST}"
