#!/usr/bin/env bash

set -euo pipefail

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
COMMAND="${1:-}"
if [[ $# -gt 0 ]]; then
  shift
fi

STACK_NAME="${OYSTERUN_RELEASE_STACK:-production}"
FOLLOW_LOGS=0

usage() {
  cat <<'EOF'
Usage:
  tool_scripts/oysterun_release_service.sh install [--no-start]
  tool_scripts/oysterun_release_service.sh start
  tool_scripts/oysterun_release_service.sh stop
  tool_scripts/oysterun_release_service.sh restart [--restore-sessions]
  tool_scripts/oysterun_release_service.sh update --channel latest|beta
  tool_scripts/oysterun_release_service.sh complete-update
  tool_scripts/oysterun_release_service.sh repair
  tool_scripts/oysterun_release_service.sh restore
  tool_scripts/oysterun_release_service.sh lifecycle-status
  tool_scripts/oysterun_release_service.sh status
  tool_scripts/oysterun_release_service.sh logs [--follow]
  tool_scripts/oysterun_release_service.sh uninstall [--stack production|staging|all]

Release service commands target the production stack by default. Override only
for development with OYSTERUN_RELEASE_STACK=<stack>.

restart --restore-sessions prepares Host restart restore state before stop/start.
update and restore-aware restart ask the running local Host to schedule the
single durable lifecycle transaction using its persisted Node/npm identity.
EOF
}

run_host_lifecycle_request() {
  local action="$1"
  local kind="${2:-}"
  local channel="${3:-}"
  shift 3 || true
  local service_args=("$@")
  local target_stack="${STACK_NAME}"
  (
    source "${SCRIPT_DIR}/oysterun_service_common.sh"
    STACK_NAME="${target_stack}"
    if [[ "${#service_args[@]}" -gt 0 ]]; then
      parse_common_args "${service_args[@]}"
    else
      parse_common_args
    fi
    configure_stack_runtime
    require_host_port_configured
    local bootstrap_node=""
    local node_bin=""
    local npm_cli=""
    local identity_digest=""
    local identity_path=""
    local lifecycle_args=(--action "${action}")
    bootstrap_node="$(resolve_bootstrap_node_command_path)"
    load_host_node_npm_lifecycle_bundle verify-persisted "${bootstrap_node}"
    node_bin="${NODE_NPM_BUNDLE_NODE_PATH}"
    npm_cli="${NODE_NPM_BUNDLE_NPM_CLI_PATH}"
    identity_digest="${NODE_NPM_BUNDLE_IDENTITY_DIGEST}"
    identity_path="${NODE_NPM_BUNDLE_IDENTITY_PATH}"
    if [[ -n "${kind}" ]]; then
      lifecycle_args+=(--kind "${kind}")
    fi
    if [[ -n "${channel}" ]]; then
      lifecycle_args+=(--channel "${channel}")
    fi
    OYSTERUN_CONFIG_DIR="${CONFIG_DIR}" \
      OYSTERUN_PORT="${HOST_PORT}" \
      OYSTERUN_NODE_BIN="${node_bin}" \
      OYSTERUN_NPM_CLI="${npm_cli}" \
      OYSTERUN_NODE_NPM_IDENTITY_DIGEST="${identity_digest}" \
      OYSTERUN_NODE_NPM_IDENTITY_PATH="${identity_path}" \
      "${node_bin}" "${ROOT_DIR}/host-service/cli/run-host-lifecycle.mjs" \
        "${lifecycle_args[@]}"
  )
}

print_login_qr_after_service_ready() {
  local service_args=("$@")
  local target_stack="${STACK_NAME}"
  (
    source "${SCRIPT_DIR}/oysterun_service_common.sh"
    STACK_NAME="${target_stack}"
    if [[ "${#service_args[@]}" -gt 0 ]]; then
      parse_common_args "${service_args[@]}"
    else
      parse_common_args
    fi
    configure_stack_runtime
    local bootstrap_node=""
    local node_bin=""
    bootstrap_node="$(resolve_bootstrap_node_command_path)"
    if ! load_host_node_npm_lifecycle_bundle verify-persisted "${bootstrap_node}"; then
      echo "[oysterun-service] persisted Host Node identity unavailable; cannot print login QR" >&2
      exit 1
    fi
    node_bin="${NODE_NPM_BUNDLE_NODE_PATH}"
    cd "${ROOT_DIR}"
    OYSTERUN_CONFIG_DIR="${CONFIG_DIR}" \
      OYSTERUN_PORT="${HOST_PORT}" \
      OYSTERUN_NODE_BIN="${NODE_NPM_BUNDLE_NODE_PATH}" \
      OYSTERUN_NPM_CLI="${NODE_NPM_BUNDLE_NPM_CLI_PATH}" \
      OYSTERUN_NODE_NPM_IDENTITY_DIGEST="${NODE_NPM_BUNDLE_IDENTITY_DIGEST}" \
      OYSTERUN_NODE_NPM_IDENTITY_PATH="${NODE_NPM_BUNDLE_IDENTITY_PATH}" \
      "${node_bin}" host-service/setup.mjs --show-qr
  ) || {
    echo "[oysterun-service] Login QR unavailable. Run 'oysterun show-qr' after setup." >&2
  }
}

case "${COMMAND}" in
  install)
    exec "${SCRIPT_DIR}/install_oysterun_launch_agents.sh" --stack "${STACK_NAME}" "$@"
    ;;
  start)
    "${SCRIPT_DIR}/start_oysterun.sh" --stack "${STACK_NAME}" "$@"
    print_login_qr_after_service_ready "$@"
    ;;
  stop)
    exec "${SCRIPT_DIR}/stop_oysterun.sh" --stack "${STACK_NAME}" "$@"
    ;;
  restart)
    RESTORE_SESSIONS=0
    RESTART_ARGS=()
    RESTART_QR_ARGS=()
    while [[ $# -gt 0 ]]; do
      case "$1" in
        --restore-sessions)
          RESTORE_SESSIONS=1
          shift
          ;;
        --expected-retained-current-host-cwd)
          [[ $# -ge 2 ]] || { echo "[oysterun-service] error: $1 requires a value" >&2; exit 2; }
          RESTART_ARGS+=("$1" "$2")
          shift 2
          ;;
        --expected-target-service-definition-sha256)
          [[ $# -ge 2 ]] || { echo "[oysterun-service] error: $1 requires a value" >&2; exit 2; }
          RESTART_ARGS+=("$1" "$2")
          shift 2
          ;;
        *)
          RESTART_ARGS+=("$1")
          RESTART_QR_ARGS+=("$1")
          shift
          ;;
      esac
    done
    if [[ "${RESTORE_SESSIONS}" -eq 1 ]]; then
      if [[ "${#RESTART_ARGS[@]}" -gt 0 ]]; then
        run_host_lifecycle_request run restart_only "" "${RESTART_ARGS[@]}"
      else
        run_host_lifecycle_request run restart_only ""
      fi
    elif [[ "${#RESTART_ARGS[@]}" -gt 0 ]]; then
      "${SCRIPT_DIR}/restart_oysterun.sh" --stack "${STACK_NAME}" "${RESTART_ARGS[@]}"
      if [[ "${#RESTART_QR_ARGS[@]}" -gt 0 ]]; then
        print_login_qr_after_service_ready "${RESTART_QR_ARGS[@]}"
      else
        print_login_qr_after_service_ready
      fi
    else
      "${SCRIPT_DIR}/restart_oysterun.sh" --stack "${STACK_NAME}"
      print_login_qr_after_service_ready
    fi
    ;;
  update)
    UPDATE_CHANNEL=""
    UPDATE_ARGS=()
    while [[ $# -gt 0 ]]; do
      case "$1" in
        --channel)
          [[ $# -ge 2 ]] || { echo "[oysterun-service] error: --channel requires latest or beta" >&2; exit 2; }
          UPDATE_CHANNEL="$2"
          shift 2
          ;;
        *)
          UPDATE_ARGS+=("$1")
          shift
          ;;
      esac
    done
    case "${UPDATE_CHANNEL}" in
      latest)
        if [[ "${#UPDATE_ARGS[@]}" -gt 0 ]]; then
          run_host_lifecycle_request run update_latest_and_restart latest "${UPDATE_ARGS[@]}"
        else
          run_host_lifecycle_request run update_latest_and_restart latest
        fi
        ;;
      beta)
        if [[ "${#UPDATE_ARGS[@]}" -gt 0 ]]; then
          run_host_lifecycle_request run update_beta_and_restart beta "${UPDATE_ARGS[@]}"
        else
          run_host_lifecycle_request run update_beta_and_restart beta
        fi
        ;;
      *)
        echo "[oysterun-service] error: service:update requires --channel latest or beta" >&2
        exit 2
        ;;
    esac
    ;;
  complete-update)
    run_host_lifecycle_request run complete_update_and_restart "" "$@"
    ;;
  repair)
    run_host_lifecycle_request run repair_and_restart "" "$@"
    ;;
  restore)
    run_host_lifecycle_request run restore_and_restart "" "$@"
    ;;
  lifecycle-status)
    run_host_lifecycle_request status "" "" "$@"
    ;;
  preflight)
    exec "${SCRIPT_DIR}/preflight_oysterun_restart.sh" --stack "${STACK_NAME}" "$@"
    ;;
  status)
    exec "${SCRIPT_DIR}/status_oysterun_launch_agents.sh" --stack "${STACK_NAME}" "$@"
    ;;
  logs)
    while [[ $# -gt 0 ]]; do
      case "$1" in
        --follow|-f)
          FOLLOW_LOGS=1
          shift
          ;;
        *)
          echo "[oysterun-service] error: unknown logs argument: $1" >&2
          exit 2
          ;;
      esac
    done
    source "${SCRIPT_DIR}/oysterun_service_common.sh"
    configure_stack_runtime
    if [[ "${FOLLOW_LOGS}" -eq 1 ]]; then
      exec tail -n 200 -f "${HOST_LOG}"
    fi
    exec tail -n 200 "${HOST_LOG}"
    ;;
  uninstall)
    exec "${SCRIPT_DIR}/uninstall_oysterun_launch_agents.sh" --stack "${STACK_NAME}" "$@"
    ;;
  ""|-h|--help|help)
    usage
    ;;
  *)
    echo "[oysterun-service] error: unknown command: ${COMMAND}" >&2
    usage >&2
    exit 2
    ;;
esac
