#!/usr/bin/env bash
#
# scripts/update_prod.sh — atualização segura de uma instalação já inicializada.
#
# ORDEM INVIOLÁVEL: preflight → garantir stack viva → BACKUP (banco + storage) ANTES
# de qualquer ação de código → git pull → assets → build (antes do down) → down/up
# seguros → migrações/otimizações → verificação. Se o backup não puder ser provado,
# a atualização NÃO começa.
#
# DRY-RUN É O PADRÃO. Não depende de `make`.
#
# Uso: scripts/update_prod.sh [--execute] [--dry-run] [--no-pull] [--allow-dirty] [--cache]
set -Eeuo pipefail

ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd -P)"
umask 077
DRY_RUN=1
ALLOW_DIRTY=0
BUILD_NO_CACHE=1
NO_PULL=0
BACKUP_ONLY=0
SCRIPT_KIND=update

usage() {
    cat <<'EOF'
scripts/update_prod.sh — atualização de uma instalação existente (produção)

  --execute       aplica o plano (padrão: dry-run, sem nenhuma mutação)
  --dry-run       força o modo de simulação (padrão)
  --no-pull       não faz git fetch/pull (usa o código já presente no checkout)
  --backup-only   só pré-checagem + start + backup de banco/storage (operação diária)
  --allow-dirty   permite rodar com a árvore git suja (produção deve usar um commit)
  --cache         reutiliza o cache de build do Docker (padrão: build --no-cache)
  -h, --help      esta ajuda

Fases (scripts/update/):
  00-preflight    .env (APP_KEY obrigatória), ferramentas, estrutura, espaço, git
  01-ensure-stack sobe (start, sem recriar) a stack parada para poder ler o banco
  02-backup       pg_dump validado + media:backup (offsite) + tar do RustFS/storage
  03-code         git fetch/pull --ff-only (a menos de --no-pull)
  04-assets       npm ci + npm run build (imagem Node pinada)
  05-build        tag da imagem anterior + build da nova imagem (ANTES do down)
  06-switch       down seguro, composer install (vendor anterior preservado), up --wait
  07-migrate      autoload, migrate --force --isolated, bucket, optimize, reload/worker
  08-verify       saúde HTTP (portal/CMS), Caddy, migrações, SBOM e relatório

Rollback automático cobre a imagem (tag :previous) e o vendor (restaurado se o
composer falhar). O banco é restaurado MANUALMENTE a partir do dump registrado no
log; o script nunca faz reset de git nem restaura banco por conta própria.
EOF
}

while [ $# -gt 0 ]; do
    case "$1" in
        --execute) DRY_RUN=0 ;;
        --dry-run) DRY_RUN=1 ;;
        --no-pull) NO_PULL=1 ;;
        --backup-only) BACKUP_ONLY=1 ;;
        --allow-dirty) ALLOW_DIRTY=1 ;;
        --cache) BUILD_NO_CACHE=0 ;;
        -h | --help)
            usage
            exit 0
            ;;
        *)
            printf 'update_prod: flag desconhecida: %s (use --help)\n' "$1" >&2
            exit 2
            ;;
    esac
    shift
done

export ROOT DRY_RUN ALLOW_DIRTY BUILD_NO_CACHE NO_PULL BACKUP_ONLY SCRIPT_KIND
# shellcheck source=scripts/lib/common.sh
. "$ROOT/scripts/lib/common.sh"

if [ "$BACKUP_ONLY" = 1 ]; then
    log "modo: somente backup (sem pull/build/down/migrate)"
    run_lifecycle update 00-preflight 01-ensure-stack 02-backup
    exit $?
fi

run_lifecycle update \
    00-preflight \
    01-ensure-stack \
    02-backup \
    03-code \
    04-assets \
    05-build \
    06-switch \
    07-migrate \
    08-verify
