#!/usr/bin/env bash
set -euo pipefail

INSTALL_DIR=""
BACKUP_DIR="/opt/tg-sales-archive-backups"

usage() {
  cat <<'USAGE'
Usage:
  bash backup.sh [--install-dir /opt/tg-sales-archive] [--backup-dir /opt/tg-sales-archive-backups]
USAGE
}

while [[ $# -gt 0 ]]; do
  case "$1" in
    --install-dir)
      INSTALL_DIR="${2:-}"
      shift 2
      ;;
    --install-dir=*)
      INSTALL_DIR="${1#*=}"
      shift
      ;;
    --backup-dir)
      BACKUP_DIR="${2:-}"
      shift 2
      ;;
    --backup-dir=*)
      BACKUP_DIR="${1#*=}"
      shift
      ;;
    -h|--help)
      usage
      exit 0
      ;;
    *)
      echo "Unknown argument: $1" >&2
      usage
      exit 1
      ;;
  esac
done

if [[ -z "$INSTALL_DIR" ]]; then
  if [[ -f ./docker-compose.prod.yml ]]; then
    INSTALL_DIR="$(pwd)"
  else
    INSTALL_DIR="/opt/tg-sales-archive"
  fi
fi

cd "$INSTALL_DIR"

if [[ ! -f docker-compose.prod.yml || ! -f .env ]]; then
  echo "docker-compose.prod.yml or .env not found in $INSTALL_DIR" >&2
  exit 1
fi

set -a
# shellcheck disable=SC1091
. "$INSTALL_DIR/.env"
set +a

COMPOSE=(docker compose -f "$INSTALL_DIR/docker-compose.prod.yml")
STAMP="$(date +%Y%m%d_%H%M%S)"
BACKUP_PATH="$BACKUP_DIR/$STAMP"

mkdir -p "$BACKUP_PATH"
chmod 700 "$BACKUP_PATH"

echo "SECURITY WARNING:"
echo ".env contains production passwords, APP_KEY, database password, MinIO secret and internal tokens."
echo "Encrypt this backup. Do not send it to developers. Do not upload it to Git."
echo

cp "$INSTALL_DIR/.env" "$BACKUP_PATH/.env"
chmod 600 "$BACKUP_PATH/.env"
cp "$INSTALL_DIR/docker-compose.prod.yml" "$BACKUP_PATH/docker-compose.prod.yml"

"${COMPOSE[@]}" exec -T mysql \
  sh -c 'mysqldump -u"$MYSQL_USER" -p"$MYSQL_PASSWORD" "$MYSQL_DATABASE" --single-transaction --quick --no-tablespaces' \
  > "$BACKUP_PATH/mysql.sql"

helper_image="$("${COMPOSE[@]}" ps -q backend | xargs -r docker inspect --format '{{ .Image }}' 2>/dev/null || true)"
if [[ -z "$helper_image" ]]; then
  helper_image="${BACKEND_IMAGE:-tg-sales-backend:phase10}"
fi

backup_volume() {
  local volume="$1"
  local archive="$2"

  if ! docker volume inspect "$volume" >/dev/null 2>&1; then
    echo "Skip missing volume: $volume" >&2
    return
  fi

  docker run --rm \
    -v "$volume":/volume:ro \
    -v "$BACKUP_PATH":/backup \
    "$helper_image" tar czf "/backup/$archive" -C /volume .
}

backup_volume tg_sales_mysql_data mysql_data_volume.tar.gz
backup_volume tg_sales_minio_data minio_data_volume.tar.gz
backup_volume tg_sales_tg_sessions tg_sessions_volume.tar.gz
backup_volume tg_sales_backend_storage backend_storage_volume.tar.gz
backup_volume tg_sales_redis_data redis_data_volume.tar.gz

{
  echo "created_at=$STAMP"
  echo "install_dir=$INSTALL_DIR"
  echo "backend_image=${BACKEND_IMAGE:-tg-sales-backend:phase10}"
  echo "worker_image=${WORKER_IMAGE:-tg-sales-worker:phase10}"
  "${COMPOSE[@]}" ps || true
  "${COMPOSE[@]}" images || true
} > "$BACKUP_PATH/VERSION.txt"

(
  cd "$BACKUP_PATH"
  sha256sum .env docker-compose.prod.yml mysql.sql VERSION.txt *.tar.gz > SHA256SUMS
)

echo "Backup created:"
echo "$BACKUP_PATH"
