#!/usr/bin/env bash
#
# tools/runtime.sh — fonte ÚNICA do runtime de containers do projeto (docker | podman).
#
# Uso (scripts):
#   . "$ROOT/tools/runtime.sh"
#   COMPOSE=("${ENGINE[@]}" compose -p "$PROJECT" --env-file .env "${COMPOSE_FILES[@]}")
#   "${ENGINE[@]}" run "${RUN_ARGS[@]}" -v "$ROOT":/app$MOUNT_LABEL ...
#
# Uso (Makefile/CLI):
#   tools/runtime.sh --engine        # docker | podman
#   tools/runtime.sh --files         # "-f docker-compose.yml [-f docker-compose.podman.yml]"
#   tools/runtime.sh --summary       # uma linha para `make ports`
#
# Resolução (ordem): $CONTAINER_RUNTIME → `.env` (CONTAINER_RUNTIME) → `docker`.
# **Docker é o padrão** (dev = prod, ADR-045); **podman** é opt-in explícito de desenvolvimento
# (`make podman-prepare` / `make runtime RUNTIME=podman`) e nunca é usado em produção
# (`scripts/update_prod.sh` recusa).
#
# Diferenças que o helper concentra (nada de `if podman` espalhado pelos scripts):
#   - **podman** acrescenta `docker-compose.podman.yml` (userns keep-id + label=disable,
#     ver o cabeçalho daquele arquivo) e roda os `docker run` com os mesmos flags;
#   - **MOUNT_LABEL** é o sufixo SELinux do bind mount: `:Z` no Docker, **vazio** no podman
#     (lá o container roda com `label=disable`; relabel recursivo é caro e falha no PGDATA);
#   - **CONTAINER_ENGINE/VOLUME_PROJECT** nunca são adivinhados: o projeto é o mesmo
#     `tools/project-name.sh` em todos os pontos de entrada.
#
# `podman compose` é um wrapper de um provider externo (`docker-compose` ou `podman-compose`);
# ele só funciona com o `podman.socket` do usuário ativo — `make podman-prepare` garante isso.
#
# NÃO use `set -euo` no topo: o arquivo é `source`-ado por scripts que já escolhem as próprias
# opções (ex.: check.sh roda com `set -uo pipefail`, sem `-e` para acumular falhas).

RUNTIME_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"

runtime_env_value() {
    local key="$1"
    [ -f "$RUNTIME_ROOT/.env" ] || return 0
    grep -E "^${key}=" "$RUNTIME_ROOT/.env" | head -1 | cut -d= -f2- \
        | sed -E 's/^"(.*)"$/\1/; s/^'"'"'(.*)'"'"'$/\1/' || true
}

runtime_resolve() {
    local requested="${CONTAINER_RUNTIME:-}"
    [ -n "$requested" ] || requested="$(runtime_env_value CONTAINER_RUNTIME)"
    requested="${requested:-docker}"

    case "$requested" in
        docker)
            RUNTIME="docker"
            ENGINE=(docker)
            COMPOSE_FILES=(-f docker-compose.yml)
            RUN_ARGS=()
            MOUNT_LABEL=":Z"
            ;;
        podman)
            RUNTIME="podman"
            ENGINE=(podman)
            COMPOSE_FILES=(-f docker-compose.yml -f docker-compose.podman.yml)
            RUN_ARGS=(--userns=keep-id --security-opt label=disable)
            MOUNT_LABEL=""
            # O provider externo imprime um banner em stderr a cada chamada; em `make check`
            # isso poluiria logs de erro. O contrato (erro ≠ 0) continua o mesmo.
            export PODMAN_COMPOSE_WARNING_LOGS="${PODMAN_COMPOSE_WARNING_LOGS:-false}"
            ;;
        *)
            printf 'runtime: CONTAINER_RUNTIME inválido (%s) — use docker ou podman.\n' "$requested" >&2
            return 2
            ;;
    esac

    # Precedência do Compose: ambiente > `.env`. Exportar garante que a decisão do helper
    # (e não um `.env` antigo) vence em todos os pontos de entrada.
    export MOUNT_LABEL
    export CONTAINER_RUNTIME="$RUNTIME"
}

if [ "${BASH_SOURCE[0]}" = "$0" ]; then
    set -Eeuo pipefail
    runtime_resolve
    case "${1:-}" in
        --engine) printf '%s\n' "${ENGINE[@]}" ;;
        --files) printf '%s\n' "${COMPOSE_FILES[@]}" ;;
        --run-args) printf '%s\n' "${RUN_ARGS[@]}" ;;
        --mount-label) printf '%s\n' "$MOUNT_LABEL" ;;
        --summary)
            printf '%s (%s)\n' "$RUNTIME" "$([ "$RUNTIME" = podman ] && echo 'rootless' || echo 'daemon')"
            ;;
        -h | --help)
            sed -n '2,28p' "$0" | sed 's/^# \{0,1\}//'
            ;;
        *)
            printf 'runtime: uso: tools/runtime.sh [--engine|--files|--run-args|--mount-label|--summary]\n' >&2
            exit 2
            ;;
    esac
else
    runtime_resolve
fi
