#!/bin/bash
# ═══════════════════════════════════════════════════════════════
# 00-bootstrap-host.sh
# Bootstrap firewalld + Docker pour USINE_APPLICATIONS
#
# A lancer une fois sur chaque host Fedora avant tout déploiement.
# Idempotent. peut être relancé sans risque.
#
# Usage. sudo ./00-bootstrap-host.sh
# ═══════════════════════════════════════════════════════════════

set -euo pipefail

# ── Configuration ─────────────────────────────────────────────
DNS_PRIMARY="${DNS_PRIMARY:-8.8.8.8}"
DNS_SECONDARY="${DNS_SECONDARY:-8.8.4.4}"
DOCKER_DAEMON_CONF="/etc/docker/daemon.json"
TEST_IMAGE="alpine:latest"
LOG_PREFIX="[bootstrap-host]"

# ── Helpers ───────────────────────────────────────────────────
log()  { echo "${LOG_PREFIX} $*"; }
warn() { echo "${LOG_PREFIX} WARN. $*" >&2; }
err()  { echo "${LOG_PREFIX} ERREUR. $*" >&2; }
die()  { err "$*"; exit 1; }

confirm() {
    local prompt="${1:-Continuer ?} [o/N] "
    read -r -p "$prompt" response
    [[ "$response" =~ ^[oOyY]$ ]] || die "Annulation utilisateur."
}

# ── Phase 0. Vérifications préalables ─────────────────────────
log "Phase 0. vérifications préalables..."

[[ $EUID -eq 0 ]] || die "Script à lancer en root (sudo $0)."

[[ -f /etc/fedora-release ]] || warn "Système non-Fedora détecté. Le script peut nécessiter des adaptations."

command -v docker        >/dev/null 2>&1 || die "Docker non installé."
command -v firewall-cmd  >/dev/null 2>&1 || die "firewalld non installé."

systemctl is-active --quiet firewalld || die "firewalld non actif. systemctl start firewalld"
systemctl is-active --quiet docker    || die "Docker non actif. systemctl start docker"

log "  Toutes les vérifications passent."

# ── Avertissement utilisateur ─────────────────────────────────
log ""
log "Ce script va."
log "  1. Réécrire ${DOCKER_DAEMON_CONF} (backup automatique)"
log "  2. Modifier la configuration firewalld (zone trusted + masquerade)"
log "  3. Redémarrer le service Docker (tous les containers vont stopper)"
log "  4. Exécuter des tests de validation (pull image alpine)"
log ""

if [[ "${1:-}" != "--force" ]]; then
    confirm "Confirmer le bootstrap ?"
fi

# ── Phase 1. Configuration daemon Docker ──────────────────────
log ""
log "Phase 1. configuration de ${DOCKER_DAEMON_CONF}..."

mkdir -p /etc/docker

if [[ -f "${DOCKER_DAEMON_CONF}" ]]; then
    BACKUP="${DOCKER_DAEMON_CONF}.bak.$(date +%Y%m%d-%H%M%S)"
    cp "${DOCKER_DAEMON_CONF}" "${BACKUP}"
    log "  Backup. ${BACKUP}"
fi

cat > "${DOCKER_DAEMON_CONF}" <<EOF
{
  "iptables": true,
  "ip-masq": true,
  "dns": ["${DNS_PRIMARY}", "${DNS_SECONDARY}"],
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "10m",
    "max-file": "3"
  }
}
EOF

log "  daemon.json écrit."

# ── Phase 2. Configuration firewalld ──────────────────────────
log ""
log "Phase 2. configuration firewalld..."

DEFAULT_ZONE=$(firewall-cmd --get-default-zone)
log "  Zone par défaut. ${DEFAULT_ZONE}"

# docker0 (toujours présent quand Docker est installé)
firewall-cmd --permanent --zone=trusted --add-interface=docker0 2>/dev/null || true
log "  docker0 ajouté à la zone trusted."

# Bridges Docker custom (br-*)
BRIDGES=$(ip -o link show | awk -F: '/br-/{print $2}' | tr -d ' ' | cut -d@ -f1)

if [[ -n "${BRIDGES}" ]]; then
    BRIDGE_COUNT=$(echo "${BRIDGES}" | wc -l)
    log "  ${BRIDGE_COUNT} bridge(s) custom détecté(s)."
    while IFS= read -r iface; do
        firewall-cmd --permanent --zone=trusted --add-interface="${iface}" 2>/dev/null || true
        log "    + ${iface}"
    done <<< "${BRIDGES}"
else
    log "  Aucun bridge custom détecté."
fi

# Masquerade sur la zone par défaut
firewall-cmd --permanent --zone="${DEFAULT_ZONE}" --add-masquerade 2>/dev/null || true
log "  Masquerade activé sur la zone ${DEFAULT_ZONE}."

# Reload
firewall-cmd --reload
log "  firewalld rechargé."

# ── Phase 3. Redémarrage Docker ───────────────────────────────
log ""
log "Phase 3. redémarrage du service Docker..."

systemctl restart docker

# Attente que Docker soit pleinement opérationnel
for i in {1..15}; do
    if docker info >/dev/null 2>&1; then
        log "  Docker opérationnel après ${i}s."
        break
    fi
    sleep 1
    if [[ $i -eq 15 ]]; then
        die "Docker ne répond pas après 15s."
    fi
done

# ── Phase 4. Tests de validation ──────────────────────────────
log ""
log "Phase 4. tests de validation..."

log "  Test 1. pull image de test (${TEST_IMAGE})..."
docker pull "${TEST_IMAGE}" >/dev/null 2>&1 || die "Pull image échoué. DNS du host probablement HS."
log "    OK"

log "  Test 2. résolution DNS depuis un container..."
if docker run --rm "${TEST_IMAGE}" nslookup archive.ubuntu.com >/dev/null 2>&1; then
    log "    OK"
else
    err "    Échec résolution DNS."
    err "    Lancer manuellement. docker run --rm alpine nslookup archive.ubuntu.com"
    exit 2
fi

log "  Test 3. connectivité HTTPS sortante depuis un container..."
if docker run --rm "${TEST_IMAGE}" wget -q --spider https://www.cloudflare.com 2>/dev/null; then
    log "    OK"
else
    err "    Échec connectivité HTTPS sortante."
    exit 2
fi

# ── Phase 5. Résumé ───────────────────────────────────────────
log ""
log "═══════════════════════════════════════════════════════════"
log " Bootstrap terminé avec succès."
log "═══════════════════════════════════════════════════════════"
log " Zone par défaut.        ${DEFAULT_ZONE}"
log " Masquerade.             actif"
log " DNS Docker.             ${DNS_PRIMARY}, ${DNS_SECONDARY}"
log " Daemon config.          ${DOCKER_DAEMON_CONF}"
log ""
log " Interfaces en zone trusted."
firewall-cmd --zone=trusted --list-interfaces | tr ' ' '\n' | sed 's/^/   - /'
log ""
log " USINE_APPLICATIONS prêt pour déploiement."
log "═══════════════════════════════════════════════════════════"