#!/usr/bin/env bash
# ============================================================
# Docker restore — rebuild volumes + images + stacks from a
# backup made by ops/docker-backup.sh.
#
# Order matters:
#   1. load locally-built images (docker load)   → images/
#   2. recreate + fill every named volume         → volumes/
#   3. bring stacks up from their compose files    → compose/
#      (public images are pulled automatically by compose)
#
# Usage (run as root on the NEW server, after `docker` is installed):
#   ops/docker-restore.sh --dir <backup-dir> [options]
#
# Options:
#   --dir DIR        docker backup dir (default: newest backups/docker-*)
#   --volumes-only   only restore volumes (no image load, no compose up)
#   --images-only    only load images
#   --no-up          restore images+volumes but do NOT run compose up
#   --only NAME      restore a single volume by name (with --volumes-only)
#   --yes            don't prompt
#
# ⚠️  Restoring a volume OVERWRITES that volume's current contents.
# NOTE: compose stacks were saved under compose/<escaped-path>/ together
#   with their .env. Review each before `up` — paths/ports/domains may
#   differ on the new host. This script brings them up in place from the
#   backup copy; move them to their real locations first if you prefer.
# ============================================================
set -uo pipefail

REPO_ROOT="/home/ashraffarid2010/halavoice.store"
DIR="" ; MODE="all" ; ONLY="" ; DO_UP=1 ; ASSUME_YES=0
while [ $# -gt 0 ]; do
  case "$1" in
    --dir) DIR="$2"; shift ;;
    --volumes-only) MODE="volumes" ;;
    --images-only) MODE="images" ;;
    --no-up) DO_UP=0 ;;
    --only) ONLY="$2"; shift ;;
    --yes) ASSUME_YES=1 ;;
    -h|--help) sed -n '2,32p' "$0"; exit 0 ;;
    *) echo "unknown arg: $1" >&2; exit 2 ;;
  esac; shift
done

log(){ echo -e "\033[1;36m[docker-restore]\033[0m $*"; }
ok(){ echo -e "\033[1;32m[ ok ]\033[0m $*"; }
warn(){ echo -e "\033[1;33m[warn]\033[0m $*" >&2; }
die(){ echo -e "\033[1;31m[FAIL]\033[0m $*" >&2; exit 1; }

[ "$(id -u)" = 0 ] || die "run as root (sudo)"
command -v docker >/dev/null || die "docker not installed on this host"
[ -n "$DIR" ] || DIR="$(ls -1dt "$REPO_ROOT"/backups/docker-* 2>/dev/null | head -1)"
[ -n "$DIR" ] && [ -d "$DIR" ] || die "docker backup dir not found (pass --dir)"
log "Restoring from: $DIR"

if [ "$ASSUME_YES" != 1 ]; then
  warn "Restoring volumes OVERWRITES their current contents on this host."
  read -r -p "  Proceed? [type YES]: " a; [ "$a" = "YES" ] || die "aborted"
fi

# ---- 1) images ----
load_images() {
  local idir="$DIR/images"
  [ -d "$idir" ] || { warn "no images/ in backup"; return; }
  local n=0
  for f in "$idir"/*.tar.gz; do
    [ -e "$f" ] || continue
    log "load image: $(basename "$f" .tar.gz)"
    if gzip -dc "$f" | docker load >/dev/null 2>&1; then n=$((n+1)); else warn "  load failed: $f"; fi
  done
  ok "images loaded: $n"
}

# ---- 2) volumes ----
restore_volumes() {
  local vdir="$DIR/volumes"
  [ -d "$vdir" ] || { warn "no volumes/ in backup"; return; }
  # ensure an alpine image is available for the tar helper
  docker image inspect alpine >/dev/null 2>&1 || docker pull alpine >/dev/null 2>&1 || \
    { [ -f "$DIR/images/alpine_latest.tar.gz" ] && gzip -dc "$DIR/images/alpine_latest.tar.gz" | docker load >/dev/null 2>&1; }
  local n=0
  for f in "$vdir"/*.tar.gz; do
    [ -e "$f" ] || continue
    local vol; vol="$(basename "$f" .tar.gz)"
    [ -n "$ONLY" ] && [ "$vol" != "$ONLY" ] && continue
    log "volume: $vol"
    docker volume create "$vol" >/dev/null 2>&1 || true
    if docker run --rm -v "$vol":/to -v "$vdir":/from:ro alpine \
         sh -c "rm -rf /to/* /to/..?* /to/.[!.]* 2>/dev/null; tar xzf /from/$vol.tar.gz -C /to" 2>/dev/null; then
      n=$((n+1)); ok "  restored $vol"
    else warn "  failed: $vol"; fi
  done
  ok "volumes restored: $n"
}

# ---- 3) compose up ----
compose_up() {
  local cdir="$DIR/compose"
  [ -d "$cdir" ] || { warn "no compose/ in backup"; return; }
  command -v docker-compose >/dev/null 2>&1 && COMPOSE="docker-compose" || COMPOSE="docker compose"
  log "compose stacks available (review before bringing up):"
  find "$cdir" -maxdepth 2 -name 'docker-compose.y*ml' -o -name 'compose.y*ml' 2>/dev/null | sed 's#^#    #'
  echo
  warn "Stacks are NOT auto-started. Review paths/ports/domains, move each to its"
  warn "real location, then bring it up, e.g.:"
  echo "    cd <stack-dir> && $COMPOSE up -d"
  echo "  (Auto-up is skipped by design — compose paths and env usually need edits"
  echo "   on a new host. Use --no-up to silence this, or bring stacks up manually.)"
}

case "$MODE" in
  images)  load_images ;;
  volumes) restore_volumes ;;
  all)     load_images; restore_volumes; [ "$DO_UP" = 1 ] && compose_up ;;
esac

echo
ok "Docker restore finished."
echo "Reminders:"
echo "  • Containerized DBs restored via volume are crash-consistent copies; verify they start clean."
echo "  • Public images (postgres, redis, supabase, …) are pulled automatically by 'compose up'."
echo "  • Recreate any external networks/secrets your compose files expect."
