#!/usr/bin/env bash
set -Eeuo pipefail

if [[ $# -lt 2 || $# -gt 5 ]]; then
  echo "usage: $0 <package-dir> <release-id> [bun-bin] [env-file] [worker-enabled]" >&2
  exit 2
fi

source_dir=$(realpath "$1")
release_id=$2
bun_bin=$(realpath "${3:-$(command -v bun)}")
env_file=${4:-}
worker_enabled=${5:-}
service_name=pushy
install_root=/opt/pushy
release_dir="$install_root/releases/$release_id"
staging_dir="$release_dir.staging"

if [[ -z $env_file ]]; then
  source "$(dirname "$(realpath "${BASH_SOURCE[0]}")")/resolve-env-file.sh"
  env_file=$(resolve_env_file pushy-api.service)
fi

[[ -x "$bun_bin" ]] || { echo "bun executable not found: $bun_bin" >&2; exit 1; }
[[ -f "$env_file" ]] || { echo "environment file not found: $env_file" >&2; exit 1; }
[[ -f "$source_dir/lib/index.js" ]] || { echo "built package missing lib/index.js" >&2; exit 1; }
[[ -f "$source_dir/lib/worker.js" ]] || { echo "built package missing lib/worker.js" >&2; exit 1; }
[[ -f "$source_dir/lib/crescAiMarketing.js" ]] || { echo "built package missing lib/crescAiMarketing.js" >&2; exit 1; }

if [[ -z "$worker_enabled" ]]; then
  if [[ -e /etc/pushy/worker-disabled ]]; then
    worker_enabled=false
  else
    worker_enabled=true
  fi
fi
[[ "$worker_enabled" == true || "$worker_enabled" == false ]] || {
  echo "worker-enabled must be true or false" >&2
  exit 2
}

install -d -m 0755 "$install_root/releases" "$install_root/runtime" /var/cache/pushy-worker /etc/pushy
rm -rf "$staging_dir"
if [[ ! -d "$release_dir" ]]; then
  cp -a "$source_dir" "$staging_dir"
  mv "$staging_dir" "$release_dir"
fi
find "$release_dir/deploy/systemd" -type f -name '*.sh' -exec chmod 0755 {} +

previous_release=$(readlink -f "$install_root/current" 2>/dev/null || true)
previous_bun=$(readlink -f "$install_root/runtime/bun" 2>/dev/null || true)
worker_was_disabled=false
legacy_peer_was_active=false
if [[ -e /etc/pushy/worker-disabled ]]; then
  worker_was_disabled=true
fi
if systemctl is-active --quiet pushy-api-peer.service; then
  legacy_peer_was_active=true
fi
legacy_peer_migration_marker=/run/pushy-rollout/legacy-peer
legacy_peer_marker_created=false

run_release_hooks() {
  local phase=$1
  RELEASE_HOOK_PHASE="$phase" \
  RELEASE_HOOK_SERVICE_NAME="$service_name" \
  RELEASE_HOOK_INSTALL_ROOT="$install_root" \
  RELEASE_HOOK_RELEASE_DIR="$release_dir" \
  RELEASE_HOOK_RELEASE_ID="$release_id" \
  RELEASE_HOOK_PREVIOUS_DIR="$previous_release" \
  RELEASE_HOOK_BUN_BIN="$bun_bin" \
  RELEASE_HOOK_ENV_FILE="$env_file" \
  RELEASE_HOOK_WORKER_ENABLED="$worker_enabled" \
    "$release_dir/deploy/systemd/run-release-hooks.sh" "$phase"
}

run_release_hooks pre-activate

units=(pushy.target pushy-api.service pushy-api-candidate.service pushy-api-peer.service pushy-worker.service pushy-dailyjob.service pushy-dailyjob.timer pushy-cresc-ai-marketing.service pushy-cresc-ai-marketing.timer pushy-health-watchdog.service pushy-health-watchdog.timer)
rollback_dir=$(mktemp -d "$install_root/releases/.activation-rollback-XXXXXX")

cleanup_rollback() {
  rm -rf "$rollback_dir"
}

trap cleanup_rollback EXIT
for unit in "${units[@]}"; do
  if [[ -e /etc/systemd/system/$unit || -L /etc/systemd/system/$unit ]]; then
    cp -a "/etc/systemd/system/$unit" "$rollback_dir/$unit"
  else
    touch "$rollback_dir/$unit.absent"
  fi
done

rollback_activation() {
  local result=$?
  trap - ERR
  set +e
  echo "release activation failed; restoring previous systemd state" >&2
  if [[ -n $previous_release && -d $previous_release ]]; then
    ln -sfn "$previous_release" "$install_root/current.next"
    mv -Tf "$install_root/current.next" "$install_root/current"
  else
    rm -f "$install_root/current" "$install_root/current.next"
  fi
  if [[ -n $previous_bun && -x $previous_bun ]]; then
    ln -sfn "$previous_bun" "$install_root/runtime/bun.next"
    mv -Tf "$install_root/runtime/bun.next" "$install_root/runtime/bun"
  fi
  for unit in "${units[@]}"; do
    rm -f "/etc/systemd/system/$unit"
    if [[ -e $rollback_dir/$unit || -L $rollback_dir/$unit ]]; then
      cp -a "$rollback_dir/$unit" "/etc/systemd/system/$unit"
    fi
  done
  if [[ $worker_was_disabled == true ]]; then
    touch /etc/pushy/worker-disabled
  else
    rm -f /etc/pushy/worker-disabled
  fi
  if [[ $legacy_peer_marker_created == true ]]; then
    rm -f "$legacy_peer_migration_marker"
  fi
  systemctl daemon-reload
  exit "$result"
}

trap rollback_activation ERR
ln -sfn "$bun_bin" "$install_root/runtime/bun"
ln -sfn "$release_dir" "$install_root/current.next"
mv -Tf "$install_root/current.next" "$install_root/current"

for unit in "${units[@]}"; do
  install -m 0644 "$release_dir/deploy/systemd/$unit" "/etc/systemd/system/$unit"
done

if [[ "$env_file" != /root/.env.prod ]]; then
  sed -i "s#--env-file=/root/.env.prod#--env-file=$env_file#g" \
    /etc/systemd/system/pushy-api.service \
    /etc/systemd/system/pushy-api-candidate.service \
    /etc/systemd/system/pushy-api-peer.service \
    /etc/systemd/system/pushy-worker.service \
    /etc/systemd/system/pushy-dailyjob.service \
    /etc/systemd/system/pushy-cresc-ai-marketing.service
fi

if [[ "$worker_enabled" == true ]]; then
  rm -f /etc/pushy/worker-disabled
else
  touch /etc/pushy/worker-disabled
fi

# The immediately previous release let either resident API process consume a
# web update. If its peer wins that race, the new primary may stop it before it
# can restart the worker. The marker lets the new primary finish that one-time
# migration safely; future releases do not have an active legacy peer here.
if [[ $legacy_peer_was_active == true && $worker_enabled == true ]]; then
  install -d -m 0755 "$(dirname "$legacy_peer_migration_marker")"
  printf '%s\n' "$release_id" >"$legacy_peer_migration_marker"
  legacy_peer_marker_created=true
fi

systemctl daemon-reload
systemctl enable pushy.target pushy-dailyjob.timer pushy-cresc-ai-marketing.timer pushy-health-watchdog.timer
run_release_hooks post-activate
trap - ERR
cleanup_rollback
trap - EXIT
echo "staged release $release_id at $release_dir (worker=$worker_enabled)"
