#!/usr/bin/env bash

set -euo pipefail

ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
source "${ROOT_DIR}/scripts/docker-prod-common.sh"

BACKUP_ROOT="${1:-${ROOT_DIR}/backups}"
shift || true
EXTRA_VOLUMES=("$@")
TIMESTAMP="$(date -u +"%Y%m%dT%H%M%SZ")"
mkdir -p "${BACKUP_ROOT}"
BACKUP_ROOT="$(cd "${BACKUP_ROOT}" && pwd)"
BACKUP_DIR="${BACKUP_ROOT}/rentaldrivego-prod-${TIMESTAMP}"
VOLUME_BACKUP_DIR="${BACKUP_DIR}/volumes"

DEFAULT_VOLUMES=(
  "${PROJECT_NAME}_api_uploads"
  "${PROJECT_NAME}_pgmanage_prod_data"
  "${PROJECT_NAME}_postgres_prod_data"
  "${PROJECT_NAME}_redis_prod_data"
)

mkdir -p "${BACKUP_DIR}"
mkdir -p "${VOLUME_BACKUP_DIR}"

ensure_env_file
ensure_traefik_network

echo "Creating production backup in ${BACKUP_DIR}"

prod_compose up -d postgres >/dev/null

echo "Backing up PostgreSQL database..."
prod_compose exec -T postgres sh -lc 'pg_dump -U "$POSTGRES_USER" -d "$POSTGRES_DB" -Fc' > "${BACKUP_DIR}/postgres.dump"

echo "Backing up uploaded files..."
prod_compose run --rm --no-deps api bash -lc '
  mkdir -p /var/lib/rentaldrivego/storage
  tar -czf - -C /var/lib/rentaldrivego/storage .
' > "${BACKUP_DIR}/api-uploads.tar.gz"

echo "Backing up Traefik certificates..."
if traefik_compose run --rm traefik sh -lc 'test -d /letsencrypt' > /dev/null 2>&1; then
  traefik_compose run --rm traefik sh -lc '
    mkdir -p /letsencrypt
    tar -czf - -C /letsencrypt .
  ' > "${BACKUP_DIR}/traefik-letsencrypt.tar.gz"
else
  echo "Skipping Traefik certificate backup; Traefik runtime is not available."
fi

declare -a ALL_VOLUMES=("${DEFAULT_VOLUMES[@]}")

if [[ -n "${DOCKER_EXTRA_BACKUP_VOLUMES:-}" ]]; then
  # shellcheck disable=SC2206
  ALL_VOLUMES+=(${DOCKER_EXTRA_BACKUP_VOLUMES})
fi

if [[ "${#EXTRA_VOLUMES[@]}" -gt 0 ]]; then
  ALL_VOLUMES+=("${EXTRA_VOLUMES[@]}")
fi

echo "Backing up named Docker volumes..."
declare -A seen_volumes=()
for volume_name in "${ALL_VOLUMES[@]}"; do
  [[ -n "${volume_name}" ]] || continue
  if [[ -n "${seen_volumes[${volume_name}]:-}" ]]; then
    continue
  fi
  seen_volumes["${volume_name}"]=1

  if ! docker_volume_exists "${volume_name}"; then
    echo "Skipping missing volume: ${volume_name}"
    continue
  fi

  echo "  - ${volume_name}"
  backup_named_volume "${volume_name}" "${VOLUME_BACKUP_DIR}/${volume_name}.tar.gz"
done

cat > "${BACKUP_DIR}/manifest.txt" <<EOF
project=${PROJECT_NAME}
created_at_utc=${TIMESTAMP}
database_backup=postgres.dump
uploads_backup=api-uploads.tar.gz
traefik_backup=traefik-letsencrypt.tar.gz
volume_backup_dir=volumes
EOF

echo "Backup complete:"
echo "  - ${BACKUP_DIR}/postgres.dump"
echo "  - ${BACKUP_DIR}/api-uploads.tar.gz"
if [[ -f "${BACKUP_DIR}/traefik-letsencrypt.tar.gz" ]]; then
  echo "  - ${BACKUP_DIR}/traefik-letsencrypt.tar.gz"
fi
if compgen -G "${VOLUME_BACKUP_DIR}/*.tar.gz" > /dev/null; then
  echo "  - ${VOLUME_BACKUP_DIR}/*.tar.gz"
fi
echo "  - ${BACKUP_DIR}/manifest.txt"
