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

PROJECT_NAME="${PROJECT_NAME:-ecom01}"
DEPLOY_ROOT="${DEPLOY_ROOT:-/var/www/stacks/ecom01}"
REPO_DIR="${REPO_DIR:-$DEPLOY_ROOT/repo}"
COMPOSE_FILE="${COMPOSE_FILE:-docker-compose.prod.yml}"
BACKUP_ROOT="${BACKUP_ROOT:-$DEPLOY_ROOT/backups}"
BACKUP_RETENTION_DAYS="${BACKUP_RETENTION_DAYS:-14}"
TIMESTAMP="$(date +%Y%m%d-%H%M%S)"
BACKUP_DIR="$BACKUP_ROOT/$TIMESTAMP"

log() {
  printf '[%s backup] %s\n' "$PROJECT_NAME" "$*"
}

require_command() {
  if ! command -v "$1" >/dev/null 2>&1; then
    log "Missing required command: $1"
    exit 1
  fi
}

compose() {
  docker compose -p "$PROJECT_NAME" --env-file "$REPO_DIR/.env.production" -f "$REPO_DIR/$COMPOSE_FILE" "$@"
}

ensure_ready() {
  require_command docker
  require_command tar
  require_command gzip

  if [ ! -f "$REPO_DIR/.env.production" ] || [ ! -f "$REPO_DIR/$COMPOSE_FILE" ]; then
    log "Missing production env or compose file in $REPO_DIR"
    exit 1
  fi

  mkdir -p "$BACKUP_DIR"
}

backup_database() {
  local db_container
  db_container="$(compose ps -q db 2>/dev/null || true)"

  if [ -z "$db_container" ] || ! docker inspect "$db_container" >/dev/null 2>&1; then
    log "Database container is not running; skipping DB backup."
    return 0
  fi

  log "Creating database dump."
  compose exec -T db sh -lc 'mysqldump --single-transaction --quick --routines --triggers --events --default-character-set=utf8mb4 -uroot -p"$MYSQL_ROOT_PASSWORD" "$MYSQL_DATABASE"' \
    | gzip -c > "$BACKUP_DIR/database.sql.gz"
}

backup_static_files() {
  log "Archiving CDN files from admin/storage/app/public."

  if [ -d "$REPO_DIR/admin/storage/app/public" ]; then
    tar -czf "$BACKUP_DIR/cdn-public.tar.gz" -C "$REPO_DIR/admin/storage/app" public
  else
    log "No CDN public directory found; writing empty archive marker."
    printf 'missing admin/storage/app/public\n' > "$BACKUP_DIR/cdn-public.missing.txt"
  fi

  if [ -d "$REPO_DIR/frontend/public" ]; then
    log "Archiving frontend/public static assets."
    tar -czf "$BACKUP_DIR/frontend-public.tar.gz" -C "$REPO_DIR/frontend" public
  fi
}

write_manifest() {
  docker ps --format 'table {{.Names}}\t{{.Image}}\t{{.Status}}\t{{.Ports}}' > "$BACKUP_DIR/docker-ps.txt"

  {
    printf 'project=%s\n' "$PROJECT_NAME"
    printf 'created_at=%s\n' "$(date -Iseconds)"
    printf 'repo_dir=%s\n' "$REPO_DIR"
    printf 'compose_file=%s\n' "$COMPOSE_FILE"
    printf 'backup_dir=%s\n' "$BACKUP_DIR"
  } > "$BACKUP_DIR/manifest.txt"
}

cleanup_old_backups() {
  if [ "$BACKUP_RETENTION_DAYS" -gt 0 ] 2>/dev/null; then
    find "$BACKUP_ROOT" -mindepth 1 -maxdepth 1 -type d -mtime +"$BACKUP_RETENTION_DAYS" -print -exec rm -rf {} \;
  fi
}

main() {
  ensure_ready
  backup_database
  backup_static_files
  write_manifest
  cleanup_old_backups
  log "Backup finished in $BACKUP_DIR"
}

main "$@"
