#!/usr/bin/env bash
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# shellcheck source=common.sh
source "$SCRIPT_DIR/common.sh"

REUSE_ENV_FROM=""
UPDATE_PACKAGE_IMAGE=1

usage() {
  cat <<'USAGE'
Usage: ./scripts/upgrade.sh [--reuse-env-from /path/to/.env] [--keep-reused-image]

By default, --reuse-env-from creates the new .env from this package's
.env.example first, then overlays existing user settings from the old .env.
For declared configuration keys, explicit invocation variables have highest
priority, for example: INTERVAL_SECS=300 ./scripts/upgrade.sh ...
Image tags are intentionally kept from the new package so the upgraded service
actually runs the new packaged runtime and monitor images. Use
--keep-reused-image only when you intentionally want to keep previous image tags.
USAGE
}

while [[ $# -gt 0 ]]; do
  case "$1" in
    --reuse-env-from)
      REUSE_ENV_FROM="$2"
      shift 2
      ;;
    --keep-reused-image)
      UPDATE_PACKAGE_IMAGE=0
      shift
      ;;
    -h|--help)
      usage
      exit 0
      ;;
    *)
      die "unknown option: $1"
      ;;
  esac
done

overlay_reused_env() {
  local source_env="$1"
  local target_env="$2"
  local key
  local value
  local -a reused_keys=()
  local -a ignored_removed_keys=()
  local -a preserved_package_keys=()

  REUSED_ENV_KEYS=()
  parse_env_file "$source_env" || die "unable to parse reused environment: $source_env"
  while IFS= read -r key; do
    if ! template_has_env_key "$key"; then
      ignored_removed_keys+=("$key")
      continue
    fi
    case "$key" in
      PACKAGE_ARCH|PACKAGE_PLATFORM|RPKI_PLATFORM|METRICS_PLATFORM|MONITOR_PLATFORM)
        preserved_package_keys+=("$key")
        continue
        ;;
      RPKI_IMAGE|METRICS_IMAGE|PROMETHEUS_IMAGE|GRAFANA_IMAGE)
        if [[ "$UPDATE_PACKAGE_IMAGE" != "0" ]]; then
          preserved_package_keys+=("$key")
          continue
        fi
        ;;
    esac
    [[ -n "${ENV_PARSED_VALUES[$key]+x}" ]] || die "unable to read $key from reused environment: $source_env"
    value="${ENV_PARSED_VALUES[$key]}"
    env_file_set_value "$target_env" "$key" "$value"
    REUSED_ENV_KEYS["$key"]=1
    reused_keys+=("$key")
  done < <(env_file_assignment_keys "$source_env")

  log_env_key_group "reused_keys" "${reused_keys[@]}"
  log_env_key_group "ignored_removed_old_keys" "${ignored_removed_keys[@]}"
  log_env_key_group "preserved_package_keys" "${preserved_package_keys[@]}"
}

apply_invocation_env_overrides() {
  local target_env="$1"
  local key
  local -a overridden_keys=()

  for key in "${ENV_TEMPLATE_KEYS[@]}"; do
    [[ -n "${INVOCATION_ENV_OVERRIDES[$key]+x}" ]] || continue
    env_file_set_value "$target_env" "$key" "${INVOCATION_ENV_OVERRIDES[$key]}"
    overridden_keys+=("$key")
  done

  log_env_key_group "command_override_keys" "${overridden_keys[@]}"
}

log_template_only_keys() {
  local key
  local -a template_only_keys=()

  for key in "${ENV_TEMPLATE_KEYS[@]}"; do
    [[ -n "${REUSED_ENV_KEYS[$key]+x}" ]] && continue
    [[ -n "${INVOCATION_ENV_OVERRIDES[$key]+x}" ]] && continue
    template_only_keys+=("$key")
  done
  log_env_key_group "template_only_keys" "${template_only_keys[@]}"
}

load_env_template_keys "$ENV_EXAMPLE"
validate_env_file_contract "$ENV_EXAMPLE"
capture_invocation_env_overrides
REUSED_ENV_KEYS=()

if [[ -n "$REUSE_ENV_FROM" ]]; then
  [[ -f "$REUSE_ENV_FROM" ]] || die "missing reuse env file: $REUSE_ENV_FROM"
  if [[ ! -f "$ENV_FILE" ]]; then
    cp "$ENV_EXAMPLE" "$ENV_FILE"
    overlay_reused_env "$REUSE_ENV_FROM" "$ENV_FILE"
    log "created new package env from .env.example and overlaid user settings from $REUSE_ENV_FROM"
  else
    log "keeping existing env at $ENV_FILE; reuse source ignored: $REUSE_ENV_FROM"
  fi
fi

if [[ ! -f "$ENV_FILE" ]]; then
  cp "$ENV_EXAMPLE" "$ENV_FILE"
  log "created new package env from .env.example"
fi
apply_invocation_env_overrides "$ENV_FILE"
log_template_only_keys
validate_env_file_contract "$ENV_FILE"
load_env
assert_arch_compatibility
create_data_dirs
install_docker_if_missing
load_installer_images
ensure_binfmt_if_needed
verify_runtime_image
verify_metrics_image
verify_monitor_images
compose_cmd --profile core --profile sidecar --profile monitor up -d --force-recreate
"$SCRIPT_DIR/status.sh" --brief || true
