#!/usr/bin/env bash
#
# Boot do container do Rails (deploy e todo restart do Docker).
#
# POR QUE ISSO VIROU UM SCRIPT: antes era um `command:` de uma linha só no
# docker-compose.yml. Com `restart: unless-stopped` o boot passou a rodar
# sozinho — depois de queda, de reboot do servidor e de cada deploy — e um
# passo que falha em silêncio vira loop de reinício sem ninguém entender por
# quê. Aqui cada etapa diz o que está fazendo no log do container
# (`docker compose logs -f app`).
#
# ORDEM DOS PASSOS (não troque sem ler o motivo):
#   1. relógio      — só imprime, para diagnóstico (ver comentário abaixo).
#   2. pid órfão    — se o container morreu sem limpar, o Puma se recusa a subir.
#   3. gems         — o volume bundle_cache SOMBREIA os gems da imagem, então
#                     gem nova no Gemfile não chega no container só com --build.
#   4. migrations   — db:prepare: cria o banco se não existir, roda as migrations
#                     pendentes e só faz seed em banco recém-criado (idempotente).
#   5. cron         — grava o crontab do config/schedule.rb e sobe o daemon.
#   6. Puma         — processo em primeiro plano (é ele que segura o container).
set -uo pipefail

log() { echo "[boot] $*"; }

# ── 1. Relógio ───────────────────────────────────────────────────────────────
# O container NÃO tem relógio próprio: ele lê o clock do kernel do HOST. Não
# adianta rodar NTP aqui dentro (exigiria CAP_SYS_TIME e mexeria na hora do
# servidor inteiro) — quem sincroniza é o host, via chrony/NTS; ver
# deploy/ntp-seguro.sh. O que é do container é só o FUSO (TZ), fixado no
# Dockerfile. Se a linha abaixo aparecer em UTC, o rebuild da imagem não pegou.
log "relógio do container: $(date '+%Y-%m-%d %H:%M:%S %Z (%z)')  |  UTC: $(date -u '+%H:%M:%S')"

# ── 2. PID órfão do Puma ─────────────────────────────────────────────────────
rm -f tmp/pids/server.pid

# ── 3. Gems ──────────────────────────────────────────────────────────────────
if ! bundle check >/dev/null 2>&1; then
  log "gem faltando no volume bundle_cache — rodando bundle install"
  bundle install || { log "ERRO: bundle install falhou"; exit 1; }
fi

# ── 4. Migrations ────────────────────────────────────────────────────────────
# ANTES de tentar, confere o DATABASE_URL. Este projeto NÃO tem
# config/database.yml: a conexão inteira sai dessa única variável (as DB_HOST,
# DB_USER etc. do .env não são lidas por ninguém — são só documentação).
#
# POR QUE ESTA CHECAGEM EXISTE: em 27/08/2026 o .env foi recriado a partir do
# .env.example e o DATABASE_URL ficou com o valor de exemplo. O resultado foram
# 10 tentativas cuspindo 40 linhas de backtrace até uma
# `URI::InvalidURIError: ... SEU_IP` no fim — ilegível no log do Container
# Manager. Placeholder e URL vazia não são "banco fora do ar": nenhuma espera
# resolve, então falha na hora e diz o que fazer.
if [ -z "${DATABASE_URL:-}" ]; then
  log "ERRO: DATABASE_URL vazia. Sem config/database.yml, é ela que define o banco."
  log "      Formato: postgresql://USUARIO:SENHA@HOST:5432/NOME_DO_BANCO"
  exit 1
fi
case "$DATABASE_URL" in
  *SEU_IP*|*senha_segura*|*SEU_HOST*)
    log "ERRO: DATABASE_URL ainda está com o valor de EXEMPLO do .env.example:"
    log "      $(printf '%s' "$DATABASE_URL" | sed 's|://[^@]*@|://***:***@|')"
    log "      Preencha com o IP, o usuário e a senha reais do PostgreSQL."
    exit 1
    ;;
esac

# O PostgreSQL é EXTERNO ao compose: num reboot do servidor o Rails pode subir
# antes do banco aceitar conexão. Sem a espera abaixo o container sairia com
# erro e o `restart: unless-stopped` ficaria reiniciando em loop — parecendo
# problema de migration quando é só ordem de boot. 10 tentativas × 6s = 1 min.
tentativas=10
for i in $(seq 1 $tentativas); do
  log "migrations (db:prepare) — tentativa $i/$tentativas"
  if bundle exec rails db:prepare; then
    log "banco pronto e migrations aplicadas"
    break
  fi
  if [ "$i" -eq "$tentativas" ]; then
    # Aqui é falha DE VERDADE (migration quebrada ou credencial errada): sair
    # com erro é melhor do que subir a aplicação contra um schema desatualizado.
    log "ERRO: db:prepare falhou após $tentativas tentativas — veja o erro acima"
    exit 1
  fi
  log "banco indisponível ou migration falhou; nova tentativa em 6s"
  sleep 6
done

# ── 5. Cron (best-effort) ────────────────────────────────────────────────────
# Best-effort de propósito: agendamento quebrado atrasa um relatório, mas NUNCA
# pode impedir o sistema de subir. As variáveis do banco chegam ao job pelo
# dotenv quando o rake carrega o Rails — o cron não precisa herdar o ENV.
if bundle exec whenever --update-crontab && cron; then
  log "cron no ar (jobs do config/schedule.rb, no fuso ${TZ:-?})"
else
  log "AVISO: cron/crontab indisponível (rode com --build) — seguindo sem agendamento"
fi

# ── 6. Puma ──────────────────────────────────────────────────────────────────
log "subindo o Rails"
exec bundle exec rails s -b 0.0.0.0
