#!/usr/bin/env bash
# =============================================================================
#  RoKbA's Médias #23
#  Installeur de la suite arr + sabnzb + JF
#  (Sonarr, Radarr, Prowlarr, SABnzbd, Jellyfin - Docker sur Debian)
#  Usage : sudo ./rokba-medias.sh
# =============================================================================

# ----------------------------- Configuration ---------------------------------
BASE_DIR="${BASE_DIR:-/opt/medias}"   # configs des conteneurs
DATA_DIR="${DATA_DIR:-/srv/medias}"   # médias et téléchargements
DOCKER_LIB="${DOCKER_LIB:-/var/lib/docker}"  # données internes de Docker
NETWORK="medias"                # réseau docker partagé
TZ_VAL="Europe/Paris"
PUID_VAL="${SUDO_UID:-1000}"
PGID_VAL="${SUDO_GID:-1000}"

NAMES=(sonarr radarr prowlarr sabnzbd jellyfin)

DIUN_NAME="diun"
DIUN_IMAGE="crazymax/diun:latest"

declare -A IMAGE=(
  [sonarr]="lscr.io/linuxserver/sonarr:latest"
  [radarr]="lscr.io/linuxserver/radarr:latest"
  [prowlarr]="lscr.io/linuxserver/prowlarr:latest"
  [sabnzbd]="lscr.io/linuxserver/sabnzbd:latest"
  [jellyfin]="lscr.io/linuxserver/jellyfin:latest"
)
declare -A PORT=(
  [sonarr]=8989
  [radarr]=7878
  [prowlarr]=9696
  [sabnzbd]=8080
  [jellyfin]=8096
)

# ------------------------------- Couleurs ------------------------------------
B=$'\e[1m'; R=$'\e[0m'
RED=$'\e[31m'; GRN=$'\e[32m'; YEL=$'\e[33m'; CYN=$'\e[36m'; MAG=$'\e[35m'

# ------------------------------- Utilitaires ---------------------------------
pause() { read -rp "${YEL}Appuyez sur Entrée pour continuer...${R}" _; }
info()  { echo -e "${CYN}➜ $*${R}"; }
ok()    { echo -e "${GRN}✔ $*${R}"; }
warn()  { echo -e "${YEL}⚠ $*${R}"; }
err()   { echo -e "${RED}✘ $*${R}"; }

get_ip() { hostname -I 2>/dev/null | awk '{print $1}'; }

is_installed() { docker ps -a --format '{{.Names}}' 2>/dev/null | grep -qx "$1"; }
is_running()   { docker ps    --format '{{.Names}}' 2>/dev/null | grep -qx "$1"; }

installed_list() { local n; for n in "${NAMES[@]}"; do is_installed "$n" && echo "$n"; done; }
missing_list()   { local n; for n in "${NAMES[@]}"; do is_installed "$n" || echo "$n"; done; }
running_list()   { local n; for n in "${NAMES[@]}"; do is_running "$n" && echo "$n"; done; }
stopped_list()   { local n; for n in "${NAMES[@]}"; do is_installed "$n" && ! is_running "$n" && echo "$n"; done; }

# ------------------------------- Bannière ------------------------------------
banner() {
  clear
  echo -en "\033[1;31m"
  cat <<'ART'
 ____          _  __  _         _    
|  _ \   ___  | |/ / | |__     / \   
| |_) | / _ \ | ' /  | '_ \   / _ \  
|  _ < | (_) || . \  | |_) | / ___ \ 
|_| \_\ \___/ |_|\_\ |_.__/ /_/   \_\
ART
  echo -e "   Médias #23"
  echo -e "   Installeur de la suite arr + sabnzb + JF${R}\n"
}

show_containers() {
  local ip n status
  ip=$(get_ip)
  echo -e "${B}Conteneurs installés :${R}"
  local found=0
  for n in "${NAMES[@]}"; do
    if is_installed "$n"; then
      found=1
      if is_running "$n"; then status="${GRN}● en marche${R}"; else status="${RED}● arrêté${R}"; fi
      printf "  %-10s %b   http://%s:%s\n" "$n" "$status" "$ip" "${PORT[$n]}"
    fi
  done
  [[ $found -eq 0 ]] && echo -e "  ${YEL}(aucun conteneur installé)${R}"
  if is_running "$DIUN_NAME"; then
    echo -e "  ${CYN}Alertes mail de mise à jour (Diun) : actives${R}"
  elif is_installed "$DIUN_NAME"; then
    echo -e "  ${CYN}Alertes mail de mise à jour (Diun) : installées mais arrêtées${R}"
  fi
  echo
}

# ------------------------------ Prérequis ------------------------------------
check_root() {
  if [[ $EUID -ne 0 ]]; then
    err "Ce script doit être lancé en root : sudo $0"
    exit 1
  fi
}

install_docker() {
  command -v docker >/dev/null 2>&1 && return 0
  info "Installation de Docker en cours..."
  apt-get update -y && apt-get install -y docker.io ca-certificates curl \
    || { err "Échec de l'installation de Docker."; return 1; }
  systemctl enable --now docker
}

ensure_docker() {
  install_docker || return 1
  systemctl is-active --quiet docker || systemctl start docker
  docker network inspect "$NETWORK" >/dev/null 2>&1 || docker network create "$NETWORK" >/dev/null
  mkdir -p "$BASE_DIR" "$DATA_DIR"/{tv,movies,downloads/incomplete}
  chown -R "$PUID_VAL:$PGID_VAL" "$BASE_DIR" "$DATA_DIR" 2>/dev/null
  return 0
}

# ------------------------------ Conteneurs -----------------------------------
run_container() {
  local n="$1"
  local args=(
    -d --name "$n" --restart unless-stopped --network "$NETWORK"
    -e "PUID=$PUID_VAL" -e "PGID=$PGID_VAL" -e "TZ=$TZ_VAL"
    --label "diun.enable=true"
    -p "${PORT[$n]}:${PORT[$n]}"
    -v "$BASE_DIR/$n:/config"
  )
  case "$n" in
    sonarr)   args+=(-v "$DATA_DIR/tv:/tv" -v "$DATA_DIR/downloads:/downloads") ;;
    radarr)   args+=(-v "$DATA_DIR/movies:/movies" -v "$DATA_DIR/downloads:/downloads") ;;
    sabnzbd)  args+=(-v "$DATA_DIR/downloads:/downloads" -v "$DATA_DIR/downloads/incomplete:/incomplete-downloads") ;;
    jellyfin) args+=(-v "$DATA_DIR/tv:/data/tvshows" -v "$DATA_DIR/movies:/data/movies") ;;
  esac
  mkdir -p "$BASE_DIR/$n"
  chown -R "$PUID_VAL:$PGID_VAL" "$BASE_DIR/$n" 2>/dev/null
  docker run "${args[@]}" "${IMAGE[$n]}" >/dev/null
}

# Demande une sélection : numéros séparés par des espaces, "t" = tous, "0" = retour.
# Résultat dans le tableau SELECTION. Retourne 1 si retour/annulation.
choose_from() {
  local title="$1"; shift
  local list=("$@") i choice
  SELECTION=()
  while true; do
    banner
    show_containers
    echo -e "${B}${title}${R}"
    for i in "${!list[@]}"; do
      printf "  %d) %s\n" $((i + 1)) "${list[$i]}"
    done
    echo "  t) Tous"
    echo "  0) Retour"
    echo
    read -rp "Votre choix (ex: 1 3) : " choice
    case "$choice" in
      0) return 1 ;;
      t|T) SELECTION=("${list[@]}"); return 0 ;;
      "") continue ;;
      *)
        local valid=1 sel=()
        for c in $choice; do
          if [[ "$c" =~ ^[0-9]+$ ]] && (( c >= 1 && c <= ${#list[@]} )); then
            sel+=("${list[$((c-1))]}")
          else
            valid=0
          fi
        done
        if [[ $valid -eq 1 && ${#sel[@]} -gt 0 ]]; then
          SELECTION=("${sel[@]}"); return 0
        fi
        err "Choix invalide."; sleep 1
        ;;
    esac
  done
}

# ------------------------------- Actions -------------------------------------
action_install_docker() {
  if command -v docker >/dev/null 2>&1; then
    warn "Docker est déjà installé ($(docker --version 2>/dev/null))."
    pause; return
  fi
  if install_docker && command -v docker >/dev/null 2>&1; then
    ok "Docker installé ($(docker --version 2>/dev/null))."
  else
    err "Docker n'a pas pu être installé."
  fi
  pause
}

action_remove_all() {
  local rep del_conf=0 del_lib=0 n pkgs others
  if ! command -v docker >/dev/null 2>&1; then
    warn "Docker n'est pas installé : rien à supprimer."; pause; return
  fi
  banner
  show_containers
  # Conteneurs Docker qui n'appartiennent pas à la suite
  others=$(docker ps -a --format '{{.Names}}' 2>/dev/null | grep -vxF -f <(printf '%s\n' "${NAMES[@]}" "$DIUN_NAME"))

  warn "Cette action va :"
  echo "   - supprimer les conteneurs de la suite et leurs images"
  echo "   - supprimer le réseau Docker '$NETWORK'"
  if [[ -n "$others" ]]; then
    echo -e "   ${GRN}- conserver Docker : d'autres conteneurs y sont présents :${R}"
    echo "$others" | sed 's/^/       · /'
  else
    echo "   - désinstaller Docker (aucun autre conteneur détecté)"
  fi
  echo "   (vos médias dans $DATA_DIR ne sont jamais touchés)"
  echo
  read -rp "Tapez OUI pour confirmer (0 = retour) : " rep
  if [[ "$rep" != "OUI" ]]; then warn "Annulé."; pause; return; fi
  read -rp "Supprimer aussi les configurations ($BASE_DIR) ? [o/N, 0 = retour] " rep
  [[ "$rep" == "0" ]] && { warn "Annulé."; pause; return; }
  [[ "$rep" =~ ^[oOyY]$ ]] && del_conf=1
  if [[ -z "$others" ]]; then
    read -rp "Supprimer aussi les données internes de Docker ($DOCKER_LIB) ? [o/N, 0 = retour] " rep
    [[ "$rep" == "0" ]] && { warn "Annulé."; pause; return; }
    [[ "$rep" =~ ^[oOyY]$ ]] && del_lib=1
  fi

  for n in "${NAMES[@]}"; do
    if is_installed "$n"; then
      info "Suppression de $n..."
      docker stop "$n" >/dev/null 2>&1
      docker rm "$n" >/dev/null 2>&1
      docker rmi "${IMAGE[$n]}" >/dev/null 2>&1
    fi
  done
  if is_installed "$DIUN_NAME"; then
    info "Suppression de $DIUN_NAME..."
    docker stop "$DIUN_NAME" >/dev/null 2>&1
    docker rm "$DIUN_NAME" >/dev/null 2>&1
    docker rmi "$DIUN_IMAGE" >/dev/null 2>&1
  fi
  docker network rm "$NETWORK" >/dev/null 2>&1
  [[ $del_conf -eq 1 ]] && rm -rf "${BASE_DIR:?}"

  if [[ -n "$others" ]]; then
    ok "Conteneurs de la suite supprimés. Docker et vos autres conteneurs sont conservés."
    pause; return
  fi

  info "Désinstallation de Docker..."
  pkgs=$(dpkg -l 2>/dev/null | awk '/^ii/ {print $2}' | grep -E '^(docker|containerd)')
  systemctl stop docker docker.socket containerd >/dev/null 2>&1
  if [[ -n "$pkgs" ]]; then
    # shellcheck disable=SC2086
    apt-get purge -y $pkgs && apt-get autoremove -y >/dev/null 2>&1
  fi
  [[ $del_lib -eq 1 ]] && rm -rf "${DOCKER_LIB:?}"
  ok "Docker et les conteneurs ont été supprimés."
  pause
}

action_install() {
  local list=()
  mapfile -t list < <(missing_list)
  if [[ ${#list[@]} -eq 0 ]]; then
    warn "Tous les conteneurs sont déjà installés."; pause; return
  fi
  choose_from "Installer quel(s) conteneur(s) ?" "${list[@]}" || return
  local n rep cancelled=0 current=""
  read -rp "Installer : ${SELECTION[*]} ? [O/n, 0 = retour] " rep
  if [[ "$rep" =~ ^[nN0]$ ]]; then
    warn "Installation annulée."; pause; return
  fi
  echo -e "${YEL}(Ctrl+C pour annuler l'installation en cours et revenir au menu)${R}"
  trap 'cancelled=1' INT
  ensure_docker || { trap - INT; [[ $cancelled -eq 1 ]] && warn "Installation annulée." || true; pause; return; }
  for n in "${SELECTION[@]}"; do
    [[ $cancelled -eq 1 ]] && break
    info "Installation de $n..."
    current="$n"
    if docker pull "${IMAGE[$n]}" && [[ $cancelled -eq 0 ]] && run_container "$n"; then
      ok "$n installé → http://$(get_ip):${PORT[$n]}"
      current=""
    elif [[ $cancelled -eq 1 ]]; then
      break
    else
      err "Échec de l'installation de $n."
      current=""
    fi
  done
  trap - INT
  if [[ $cancelled -eq 1 ]]; then
    # nettoie le conteneur éventuellement créé à moitié (il n'existait pas avant)
    [[ -n "$current" ]] && docker rm -f "$current" >/dev/null 2>&1
    echo
    warn "Installation annulée. Retour au menu."
    sleep 1
    return
  fi
  pause
}

action_update() {
  local list=()
  mapfile -t list < <(installed_list)
  if [[ ${#list[@]} -eq 0 ]]; then
    warn "Aucun conteneur installé : rien à mettre à jour."; pause; return
  fi
  choose_from "Mettre à jour quel(s) conteneur(s) ?" "${list[@]}" || return
  local n
  for n in "${SELECTION[@]}"; do
    info "Mise à jour de $n..."
    if docker pull "${IMAGE[$n]}"; then
      docker stop "$n" >/dev/null 2>&1
      docker rm "$n" >/dev/null 2>&1
      if run_container "$n"; then ok "$n mis à jour."; else err "Échec du redémarrage de $n."; fi
    else
      err "Impossible de télécharger l'image de $n."
    fi
  done
  docker image prune -f >/dev/null 2>&1
  pause
}

action_remove() {
  local list=()
  mapfile -t list < <(installed_list)
  if [[ ${#list[@]} -eq 0 ]]; then
    warn "Aucun conteneur installé : rien à supprimer."; pause; return
  fi
  choose_from "Supprimer quel(s) conteneur(s) ?" "${list[@]}" || return
  local n rep del_conf=0
  read -rp "Supprimer aussi les configurations (${BASE_DIR}/...) ? [o/N, 0 = retour] " rep
  [[ "$rep" == "0" ]] && { warn "Annulé."; pause; return; }
  [[ "$rep" =~ ^[oOyY]$ ]] && del_conf=1
  for n in "${SELECTION[@]}"; do
    info "Suppression de $n..."
    docker stop "$n" >/dev/null 2>&1
    if docker rm "$n" >/dev/null 2>&1; then
      docker rmi "${IMAGE[$n]}" >/dev/null 2>&1
      [[ $del_conf -eq 1 ]] && rm -rf "${BASE_DIR:?}/$n"
      ok "$n supprimé."
    else
      err "Échec de la suppression de $n."
    fi
  done
  pause
}

action_start() {
  local list=()
  mapfile -t list < <(stopped_list)
  if [[ ${#list[@]} -eq 0 ]]; then
    warn "Aucun conteneur arrêté à démarrer."; pause; return
  fi
  choose_from "Démarrer quel(s) conteneur(s) ?" "${list[@]}" || return
  local n
  for n in "${SELECTION[@]}"; do
    if docker start "$n" >/dev/null 2>&1; then
      ok "$n démarré → http://$(get_ip):${PORT[$n]}"
    else
      err "Échec du démarrage de $n."
    fi
  done
  pause
}

action_stop() {
  local list=()
  mapfile -t list < <(running_list)
  if [[ ${#list[@]} -eq 0 ]]; then
    warn "Aucun conteneur en marche à arrêter."; pause; return
  fi
  choose_from "Arrêter quel(s) conteneur(s) ?" "${list[@]}" || return
  local n
  for n in "${SELECTION[@]}"; do
    info "Arrêt de $n..."
    if docker stop "$n" >/dev/null 2>&1; then
      ok "$n arrêté."
    else
      err "Échec de l'arrêt de $n."
    fi
  done
  pause
}

# --------------------- Vérification des mises à jour -------------------------
# Digest de l'image sur le registre (lscr.io redirige vers ghcr.io)
registry_digest() {
  local img="${1#lscr.io/}" repo tag tok
  repo="${img%%:*}"; tag="${img##*:}"
  tok=$(curl -fsS --max-time 15 "https://ghcr.io/token?scope=repository:${repo}:pull" 2>/dev/null \
        | sed -n 's/.*"token":"\([^"]*\)".*/\1/p')
  [[ -z "$tok" ]] && return 1
  curl -fsSI --max-time 15 -H "Authorization: Bearer $tok" \
    -H "Accept: application/vnd.oci.image.index.v1+json, application/vnd.docker.distribution.manifest.list.v2+json, application/vnd.oci.image.manifest.v1+json, application/vnd.docker.distribution.manifest.v2+json" \
    "https://ghcr.io/v2/${repo}/manifests/${tag}" 2>/dev/null \
    | tr -d '\r' | awk 'tolower($1)=="docker-content-digest:" {print $2}'
}

# Digests de l'image réellement utilisée par le conteneur
container_digests() {
  local img
  img=$(docker inspect --format '{{.Image}}' "$1" 2>/dev/null) || return 1
  docker image inspect --format '{{range .RepoDigests}}{{println .}}{{end}}' "$img" 2>/dev/null | sed 's/.*@//'
}

action_check_updates() {
  local list=() n remote locals found=0
  mapfile -t list < <(installed_list)
  if [[ ${#list[@]} -eq 0 ]]; then
    warn "Aucun conteneur installé : rien à vérifier."; pause; return
  fi
  if ! command -v curl >/dev/null 2>&1; then
    err "curl est requis pour vérifier les mises à jour (apt-get install curl)."; pause; return
  fi
  banner
  info "Vérification des mises à jour (rien n'est téléchargé ni modifié)..."
  echo
  for n in "${list[@]}"; do
    remote=$(registry_digest "${IMAGE[$n]}")
    locals=$(container_digests "$n")
    if [[ -z "$remote" || -z "$locals" ]]; then
      printf "  %-10s ${YEL}? vérification impossible${R}\n" "$n"
    elif grep -qxF "$remote" <<<"$locals"; then
      printf "  %-10s ${GRN}✔ à jour${R}\n" "$n"
    else
      printf "  %-10s ${CYN}⬆ mise à jour disponible${R}\n" "$n"
      found=1
    fi
  done
  echo
  [[ $found -eq 1 ]] && info "Utilisez l'option 3 (Mettre à jour) pour les installer."
  pause
}

# ------------------------ Alertes mail (Diun) --------------------------------
diun_install() {
  local host port user pass from to ssl="false" sched env_file n missing=()
  banner
  echo -e "${B}Configuration des alertes mail (SMTP)${R}"
  echo "Tapez 0 à n'importe quelle question (ou laissez le serveur vide) pour"
  echo "revenir en arrière. (Gmail : smtp.gmail.com, port 587, mot de passe d'application.)"
  echo
  read -rp "Serveur SMTP (0 = retour) : " host
  [[ -z "$host" || "$host" == "0" ]] && { warn "Annulé."; pause; return; }
  read -rp "Port [587] : " port; port="${port:-587}"
  [[ "$port" == "0" ]] && { warn "Annulé."; pause; return; }
  [[ "$port" == "465" ]] && ssl="true"
  read -rp "Utilisateur SMTP : " user
  [[ "$user" == "0" ]] && { warn "Annulé."; pause; return; }
  read -rsp "Mot de passe SMTP : " pass; echo
  [[ "$pass" == "0" ]] && { warn "Annulé."; pause; return; }
  read -rp "Adresse expéditeur [$user] : " from; from="${from:-$user}"
  [[ "$from" == "0" ]] && { warn "Annulé."; pause; return; }
  read -rp "Adresse destinataire : " to
  [[ "$to" == "0" ]] && { warn "Annulé."; pause; return; }
  if [[ -z "$from" || -z "$to" ]]; then err "Adresses manquantes."; pause; return; fi
  read -rp "Fréquence de vérification (cron) [0 */6 * * *] : " sched; sched="${sched:-0 */6 * * *}"
  [[ "$sched" == "0" ]] && { warn "Annulé."; pause; return; }

  ensure_docker || { pause; return; }
  mkdir -p "$BASE_DIR/$DIUN_NAME"
  env_file="$BASE_DIR/$DIUN_NAME/diun.env"
  ( umask 077
    cat > "$env_file" <<EOF
DIUN_NOTIF_MAIL_HOST=$host
DIUN_NOTIF_MAIL_PORT=$port
DIUN_NOTIF_MAIL_SSL=$ssl
DIUN_NOTIF_MAIL_USERNAME=$user
DIUN_NOTIF_MAIL_PASSWORD=$pass
DIUN_NOTIF_MAIL_FROM=$from
DIUN_NOTIF_MAIL_TO=$to
EOF
  )
  chmod 600 "$env_file"

  info "Installation de Diun..."
  docker pull "$DIUN_IMAGE" || { err "Téléchargement impossible."; pause; return; }
  docker stop "$DIUN_NAME" >/dev/null 2>&1; docker rm "$DIUN_NAME" >/dev/null 2>&1
  if docker run -d --name "$DIUN_NAME" --restart unless-stopped --network "$NETWORK" \
      --env-file "$env_file" \
      -e "TZ=$TZ_VAL" -e "LOG_LEVEL=info" \
      -e "DIUN_WATCH_WORKERS=10" -e "DIUN_WATCH_SCHEDULE=$sched" \
      -e "DIUN_PROVIDERS_DOCKER=true" -e "DIUN_PROVIDERS_DOCKER_WATCHBYDEFAULT=false" \
      -v "$BASE_DIR/$DIUN_NAME:/data" \
      -v /var/run/docker.sock:/var/run/docker.sock:ro \
      "$DIUN_IMAGE" >/dev/null; then
    ok "Diun installé : un mail sera envoyé à $to quand une mise à jour sera disponible."
    for n in $(installed_list); do
      [[ "$(docker inspect --format '{{index .Config.Labels "diun.enable"}}' "$n" 2>/dev/null)" == "true" ]] || missing+=("$n")
    done
    if [[ ${#missing[@]} -gt 0 ]]; then
      warn "Pas encore surveillés (installés avant cette option) : ${missing[*]}"
      warn "Faites l'option 3 (Mettre à jour) sur ces conteneurs pour les inclure."
    fi
  else
    err "Échec du démarrage de Diun."
  fi
  pause
}

diun_test() {
  if ! is_running "$DIUN_NAME"; then
    warn "Diun n'est pas en marche."; pause; return
  fi
  info "Envoi d'un mail de test..."
  if docker exec "$DIUN_NAME" diun notif test; then
    ok "Mail de test envoyé (vérifiez aussi les spams)."
  else
    err "Échec de l'envoi : vérifiez les paramètres SMTP (docker logs $DIUN_NAME)."
  fi
  pause
}

diun_remove() {
  local rep
  read -rp "Supprimer Diun et sa configuration mail ? [o/N] " rep
  [[ "$rep" =~ ^[oOyY]$ ]] || { warn "Annulé."; pause; return; }
  docker stop "$DIUN_NAME" >/dev/null 2>&1
  docker rm "$DIUN_NAME" >/dev/null 2>&1
  docker rmi "$DIUN_IMAGE" >/dev/null 2>&1
  rm -rf "${BASE_DIR:?}/$DIUN_NAME"
  ok "Diun supprimé."
  pause
}

action_diun() {
  local choice
  while true; do
    banner
    show_containers
    echo -e "${B}Alertes mail de mise à jour (Diun) :${R}"
    echo "  1) Installer / reconfigurer"
    echo "  2) Envoyer un mail de test"
    echo "  3) Supprimer Diun"
    echo "  0) Retour"
    echo
    read -rp "Votre choix : " choice
    case "$choice" in
      1) diun_install ;;
      2) diun_test ;;
      3) if is_installed "$DIUN_NAME"; then diun_remove; else warn "Diun n'est pas installé."; pause; fi ;;
      0) return ;;
      *) err "Choix invalide."; sleep 1 ;;
    esac
  done
}

# ------------------------------ Menu principal -------------------------------
main_menu() {
  local choice
  while true; do
    banner
    show_containers
    echo -e "${B}Menu :${R}"
    echo "  1) Installer Docker seulement"
    echo "  2) Installer les conteneurs (au choix ou tous)"
    echo "  3) Mettre à jour"
    echo "  4) Supprimer des conteneurs (au choix ou tous)"
    echo "  5) Démarrer"
    echo "  6) Arrêter des conteneurs (au choix ou tous)"
    echo "  7) Tout supprimer (Docker + conteneurs)"
    echo "  8) Vérifier les mises à jour disponibles"
    echo "  9) Alertes mail de mise à jour (Diun)"
    echo "  0) Quitter"
    echo
    read -rp "Votre choix : " choice
    case "$choice" in
      1) action_install_docker ;;
      2) action_install ;;
      3) action_update ;;
      4) action_remove ;;
      5) action_start ;;
      6) action_stop ;;
      7) action_remove_all ;;
      8) action_check_updates ;;
      9) action_diun ;;
      0) echo "À bientôt !"; exit 0 ;;
      *) err "Choix invalide."; sleep 1 ;;
    esac
  done
}

# --------------------------------- Départ ------------------------------------
check_root
if command -v docker >/dev/null 2>&1; then ensure_docker; fi
main_menu
