#!/usr/bin/env bash
#
# tools/podman-prepare.sh — prepara o HOST para o caminho OPCIONAL de desenvolvimento
# (podman rootless). **Docker é o padrão** (dev = prod) e o único runtime de produção;
# rodar este script é o ato explícito de opt-in de dev (ADR-045).
#
# O projeto continua sendo um `docker compose` (ADR-005): o podman entra como **runtime do
# host** via socket compatível com o Docker, não como um segundo jeito de configurar o app.
# Este script é idempotente e só toca o que falta:
#
#   1. podman >= 5 (é o primeiro com `podman compose` nativo);
#   2. `podman.socket` do usuário ativo (o `podman compose` fala com o provider por ele);
#   3. provider de Compose (`docker-compose` ou `podman-compose`) presente;
#   4. mapeamento de subuid/subgid do usuário (exigido pelo `userns_mode: keep-id`);
#   5. escolha persistida no `.env` (`CONTAINER_RUNTIME=podman` + `MOUNT_LABEL=`), junto com
#      porta determinística e `APP_URL` coerente (`tools/dev-env.sh --runtime=podman`);
#   6. diretórios de dados (`DATA_PATH`/`STORAGE_PATH`) criados e graváveis;
#   7. validação do Compose mesclado (`docker-compose.yml` + `docker-compose.podman.yml`).
#
# O que NÃO faz (e por quê):
#   - não instala pacotes: `dnf install` é do dono da máquina, não de um `make`;
#   - não desliga o SELinux do host: o `label=disable` é **por container**, só no override
#     do podman (o Docker do deploy continua com `:Z`);
#   - não mexe em containers em execução: quem sobe/derruba é `make up`/`make down`.
#
# Uso:
#   make podman-prepare            # prepara e persiste a escolha no .env
#   tools/podman-prepare.sh --check  # só verifica (não escreve, não inicia serviço)
#   PODMAN_PERSIST=0 make podman-prepare  # inicia o socket sem `enable` (não sobrevive ao boot)
set -Eeuo pipefail

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

CHECK=0
for arg in "$@"; do
    case "$arg" in
        --check) CHECK=1 ;;
        -h | --help) sed -n '2,30p' "$0" | sed 's/^# \{0,1\}//'; exit 0 ;;
        *) echo "podman-prepare: flag desconhecida: $arg" >&2; exit 2 ;;
    esac
done

ok() { printf '  ok  %s\n' "$*"; }
info() { printf '  ..  %s\n' "$*"; }
die() {
    printf 'podman-prepare: %s\n' "$*" >&2
    exit 1
}

step() { printf '\n== %s\n' "$*"; }

export PODMAN_COMPOSE_WARNING_LOGS=false

# ── 1. podman e versão ─────────────────────────────────────────────────────────────
step "podman"
command -v podman >/dev/null 2>&1 || die "podman não encontrado no PATH. Instale (Fedora: sudo dnf install podman)."
PODMAN_VERSION="$(podman --version 2>/dev/null | sed -E 's/.* ([0-9]+\.[0-9]+\.[0-9]+).*/\1/')"
PODMAN_MAJOR="${PODMAN_VERSION%%.*}"
[ -n "$PODMAN_MAJOR" ] || die "não consegui ler a versão do podman."
[ "$PODMAN_MAJOR" -ge 5 ] || die "podman ${PODMAN_VERSION} é antigo: 'podman compose' exige >= 5 (atualize o podman)."
ok "podman ${PODMAN_VERSION}"

ROOTLESS="$(podman info --format '{{.Host.Security.Rootless}}' 2>/dev/null || echo unknown)"
[ "$ROOTLESS" = "true" ] || die "podman não está em modo rootless (rootless=${ROOTLESS}). O preparo assume o usuário do projeto: rode como ele, sem sudo."
ok "rootless (o uid do host é mapeado 1:1 com userns keep-id)"

# ── 2. socket do usuário ───────────────────────────────────────────────────────────
step "podman.socket (user)"
SOCKET="${XDG_RUNTIME_DIR:-/run/user/$(id -u)}/podman/podman.sock"
command -v systemctl >/dev/null 2>&1 || die "systemctl ausente: este ambiente não tem systemd de usuário."
if [ "$CHECK" = 1 ]; then
    systemctl --user is-active --quiet podman.socket || die "podman.socket inativo (modo --check não inicia serviço)."
    ok "ativo: ${SOCKET}"
else
    if systemctl --user is-active --quiet podman.socket; then
        ok "já ativo: ${SOCKET}"
    else
        systemctl --user start podman.socket || die "não consegui iniciar podman.socket (systemctl --user start podman.socket)."
        ok "iniciado: ${SOCKET}"
    fi
    if [ "${PODMAN_PERSIST:-1}" = "1" ] && ! systemctl --user is-enabled --quiet podman.socket 2>/dev/null; then
        systemctl --user enable podman.socket >/dev/null 2>&1 \
            && ok "habilitado no boot" \
            || info "não consegui 'enable' (siga com 'systemctl --user enable podman.socket')"
    fi
fi
[ -S "$SOCKET" ] || die "socket não apareceu em ${SOCKET}."
info "sem linger o socket morre no logout: loginctl enable-linger $(id -un)"

# ── 3. provider de Compose ─────────────────────────────────────────────────────────
step "compose provider"
if ! PROVIDER="$(podman compose version 2>&1 | head -1)"; then
    die "sem provider de compose para o podman. Instale um: sudo dnf install podman-compose  (ou o plugin docker-compose)."
fi
case "$PROVIDER" in
    *Compose* | *compose* | *podman-compose*) ok "$PROVIDER" ;;
    *) die "provider inesperado: ${PROVIDER}" ;;
esac

# ── 4. subuid/subgid (userns keep-id) ──────────────────────────────────────────────
step "subuid/subgid"
USER_NAME="$(id -un)"
if grep -qE "^${USER_NAME}:" /etc/subuid && grep -qE "^${USER_NAME}:" /etc/subgid; then
    ok "${USER_NAME}: $(grep -E "^${USER_NAME}:" /etc/subuid | head -1 | cut -d: -f2-)"
else
    printf '  falta o mapeamento do usuário. Rode (e faça logout/login):\n' >&2
    printf '    sudo usermod --add-subuids 100000-165535 --add-subgids 100000-165535 %s\n' "$USER_NAME" >&2
    exit 1
fi

# ── 5. SELinux ─────────────────────────────────────────────────────────────────────
step "SELinux"
if command -v getenforce >/dev/null 2>&1; then
    MODE="$(getenforce 2>/dev/null || echo Unknown)"
    case "$MODE" in
        Enforcing) ok "Enforcing — os containers usam label=disable (docker-compose.podman.yml); o Docker do deploy mantém :Z" ;;
        *) info "${MODE} — nenhum ajuste necessário" ;;
    esac
else
    info "getenforce ausente — SELinux não é usado neste host"
fi

# ── 6. .env (runtime + porta determinística + APP_URL) ─────────────────────────────
step ".env"
if [ "$CHECK" = 1 ]; then
    bash "$ROOT/tools/dev-env.sh" --print
else
    bash "$ROOT/tools/dev-env.sh" --runtime=podman
    [ "$(grep -cE '^CONTAINER_RUNTIME=podman$' .env || true)" = "1" ] || die "CONTAINER_RUNTIME=podman não ficou gravado no .env."
    ok "CONTAINER_RUNTIME=podman · MOUNT_LABEL vazio"
fi

# ── 7. diretórios de dados ─────────────────────────────────────────────────────────
step "diretórios de dados"
env_value() {
    grep -E "^${1}=" .env 2>/dev/null | head -1 | cut -d= -f2- \
        | sed -E 's/^"(.*)"$/\1/; s/^'"'"'(.*)'"'"'$/\1/' || true
}
DATA_PATH_V="$(env_value DATA_PATH)"; DATA_PATH_V="${DATA_PATH_V:-./s3-local}"
STORAGE_PATH_V="$(env_value STORAGE_PATH)"; STORAGE_PATH_V="${STORAGE_PATH_V:-./storage}"
if [ "$CHECK" = 1 ]; then
    [ -d "$DATA_PATH_V" ] && [ -d "$STORAGE_PATH_V" ] || die "diretórios de dados ausentes (${DATA_PATH_V}, ${STORAGE_PATH_V})."
else
    # Cria os diretórios E o guard do git (`s3-local/.gitignore`) — ver tools/data-dirs.sh.
    bash "$ROOT/tools/data-dirs.sh" "$DATA_PATH_V" "$STORAGE_PATH_V" \
        || die "não foi possível criar os diretórios de dados (${DATA_PATH_V}, ${STORAGE_PATH_V})."
fi
[ -w "$DATA_PATH_V" ] && [ -w "$STORAGE_PATH_V" ] || die "diretórios de dados não são graváveis pelo usuário (${DATA_PATH_V}, ${STORAGE_PATH_V})."
ok "${DATA_PATH_V} · ${STORAGE_PATH_V} (dono $(id -un))"

# ── 8. validação do Compose mesclado ───────────────────────────────────────────────
step "compose (docker-compose.yml + docker-compose.podman.yml)"
PROJECT="$(bash "$ROOT/tools/project-name.sh" 2>/dev/null)"
if podman compose -p "$PROJECT" --env-file .env \
    -f docker-compose.yml -f docker-compose.podman.yml config -q 2>/dev/null; then
    ok "config válido (projeto ${PROJECT})"
else
    die "o Compose mesclado não valida — rode 'podman compose -f docker-compose.yml -f docker-compose.podman.yml config' para ver o erro."
fi

# ── 9. resumo ──────────────────────────────────────────────────────────────────────
WEB_PORT_V="$(env_value WEB_PORT)"; WEB_PORT_V="${WEB_PORT_V:-8080}"
if [ "$CHECK" = 1 ]; then
    cat <<EOS

podman-prepare: OK (--check) — pré-requisitos presentes; nada foi alterado.
  podman:   ${PODMAN_VERSION} (rootless) · socket ${SOCKET}
  provider: ${PROVIDER}
  SELinux:  ${MODE:-desconhecido}
  app:      http://localhost:${WEB_PORT_V} (quando o runtime atual for podman)

Nada foi gravado: rode 'make podman-prepare' para persistir CONTAINER_RUNTIME=podman.
EOS
    exit 0
fi

cat <<EOS

podman-prepare: OK (caminho OPCIONAL de dev — ADR-045)
  runtime:  podman (rootless) — gravado no .env como CONTAINER_RUNTIME=podman
  socket:   ${SOCKET}
  provider: ${PROVIDER}
  projeto:  ${PROJECT}
  app:      http://localhost:${WEB_PORT_V}

Próximos passos:
  make up        # sobe a stack (runtime; não valida)
  make check     # validação separada, agora atrás do podman
  make ports     # runtime, projeto, porta e diretórios resolvidos
  make runtime RUNTIME=docker   # volta ao padrão (dev = prod)
EOS
