#!/usr/bin/env bash

BACKUP_SUPPORTED_SERVICES="postgres ory-postgres clickhouse ory-clickhouse config"

backup_repo_root() {
  if [[ -n "${BACKUP_REPO_ROOT:-}" ]]; then
    printf '%s\n' "$BACKUP_REPO_ROOT"
    return
  fi

  local script_dir
  script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")/../../.." && pwd)"
  printf '%s\n' "$script_dir"
}

backup_log() {
  printf '==> %s\n' "$*"
}

backup_die() {
  printf 'ERROR: %s\n' "$*" >&2
  return 1
}

backup_require_command() {
  local command_name="$1"
  command -v "$command_name" >/dev/null 2>&1 || backup_die "required command not found: $command_name"
}

backup_utc_now() {
  date -u '+%Y-%m-%dT%H:%M:%SZ'
}

backup_timestamp() {
  date -u '+%Y%m%d-%H%M%SZ'
}

backup_git_commit() {
  local repo_root="$1"
  git -c "safe.directory=$repo_root" -C "$repo_root" rev-parse --short=12 HEAD 2>/dev/null || printf 'unknown'
}

normalize_service_filter() {
  local raw="${1:-all}"
  local normalized=""
  local candidate

  if [[ "$raw" == "all" || -z "$raw" ]]; then
    printf '%s\n' "$BACKUP_SUPPORTED_SERVICES"
    return
  fi

  raw="${raw//,/ }"
  for candidate in $raw; do
    if ! grep -qw -- "$candidate" <<<"$BACKUP_SUPPORTED_SERVICES"; then
      backup_die "unknown backup service: $candidate"
      return 1
    fi
    if ! grep -qw -- "$candidate" <<<"$normalized"; then
      normalized="${normalized:+$normalized }$candidate"
    fi
  done

  [[ -n "$normalized" ]] || backup_die "service filter must not be empty"
  printf '%s\n' "$normalized"
}

service_enabled() {
  local service="$1"
  local services="$2"
  local candidate

  for candidate in $services; do
    [[ "$candidate" == "$service" ]] && return 0
  done

  return 1
}

backup_require_path() {
  local path="$1"
  [[ -e "$path" ]] || backup_die "required path not found: $path"
}

backup_container_running() {
  local container="$1"
  docker inspect -f '{{.State.Running}}' "$container" 2>/dev/null | grep -qx 'true'
}

backup_require_container() {
  local container="$1"
  backup_container_running "$container" || backup_die "container is not running: $container"
}

backup_redact_env() {
  local source_file="$1"
  local target_file="$2"

  sed -E '/^[[:space:]]*#/! s/^([^=]*(SECRET|PASSWORD|TOKEN|KEY|PRIVATE|CLIENT_SECRET|COOKIE)[^=]*)=.*/\1=REDACTED/I' "$source_file" >"$target_file"
}

backup_checksum_file() {
  local backup_dir="$1"
  (
    cd "$backup_dir"
    find . -type f ! -name 'checksums.sha256' -print0 \
      | sort -z \
      | xargs -0 sha256sum
  ) >"$backup_dir/checksums.sha256"
}

backup_verify_checksums() {
  local backup_dir="$1"
  backup_require_path "$backup_dir/checksums.sha256"
  (
    cd "$backup_dir"
    sha256sum -c checksums.sha256
  )
}

backup_safe_tar() {
  local source_path="$1"
  local target_base="$2"
  local source_parent
  local source_name

  [[ -e "$source_path" ]] || return 0

  source_parent="$(dirname "$source_path")"
  source_name="$(basename "$source_path")"

  if command -v zstd >/dev/null 2>&1; then
    tar --zstd -cf "${target_base}.tar.zst" -C "$source_parent" "$source_name"
  else
    tar -czf "${target_base}.tar.gz" -C "$source_parent" "$source_name"
  fi
}
