#!/bin/bash
#
# WireGuard Manager pour Debian 13 (Trixie)
# Script d'installation et de gestion des clients
#

set -e

# === Configuration ===
WG_DIR="/etc/wireguard"
WG_CONF="$WG_DIR/wg0.conf"
WG_SUBNET="172.26.18"
WG_MASK="/28"
WG_SERVER_IP="${WG_SUBNET}.1"
WG_PORT="51820"

# === Couleurs ===
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
CYAN='\033[0;36m'
NC='\033[0m' # No Color

# === Fonctions utilitaires ===

print_header() {
    echo ""
    echo -e "${CYAN}════════════════════════════════════════════════════════════${NC}"
    echo -e "${CYAN}  $1${NC}"
    echo -e "${CYAN}════════════════════════════════════════════════════════════${NC}"
    echo ""
}

print_success() {
    echo -e "${GREEN}✓ $1${NC}"
}

print_error() {
    echo -e "${RED}✗ $1${NC}"
}

print_info() {
    echo -e "${BLUE}→ $1${NC}"
}

print_warning() {
    echo -e "${YELLOW}⚠ $1${NC}"
}

check_root() {
    if [[ $EUID -ne 0 ]]; then
        print_error "Ce script doit être exécuté en tant que root."
        print_info "Utilisez : sudo $0"
        exit 1
    fi
}

# Détecter l'interface réseau principale (celle avec la route par défaut)
get_main_interface() {
    ip route show default | awk '/default/ {print $5}' | head -n1
}

# === Fonction d'installation client ===

install_wireguard_client() {
    clear
    print_header "      Installation de WireGuard (client) sur Debian"

    # Vérifier si déjà installé
    if command -v wg &> /dev/null; then
        print_success "WireGuard est déjà installé."
        echo ""
        echo "Appuyez sur ENTRÉE pour revenir au menu..."
        read -r
        show_menu
        return
    fi

    # === Étape 1 : Mise à jour et installation des paquets ===
    print_info "Mise à jour des dépôts..."
    apt-get update -qq
    print_success "Dépôts mis à jour."

    print_info "Installation de WireGuard..."
    apt-get install -y wireguard wireguard-tools iptables resolvconf
    print_success "Paquets WireGuard installés."

    # Vérification
    if ! command -v wg &> /dev/null; then
        print_error "Échec de l'installation de WireGuard."
        exit 1
    fi
    print_info "Version WireGuard : $(wg --version)"

    # Créer le répertoire de configuration
    mkdir -p "$WG_DIR"
    chmod 700 "$WG_DIR"

    echo ""
    print_success "WireGuard client est installé !"
    echo ""
    print_info "Utilisez l'option 'Importer une configuration client' pour configurer le tunnel."
    echo ""
    echo "Appuyez sur ENTRÉE pour revenir au menu..."
    read -r
    show_menu
}

# === Fonction d'import de configuration client ===

import_client_config() {
    clear
    print_header "        Import d'une configuration client"

    # Vérifier si WireGuard est installé
    if ! command -v wg &> /dev/null; then
        print_error "WireGuard n'est pas installé."
        print_info "Installez d'abord WireGuard avec l'option 'Installer WireGuard (client)'."
        echo ""
        echo "Appuyez sur ENTRÉE pour revenir au menu..."
        read -r
        show_menu
        return
    fi

    echo ""
    echo "Comment souhaitez-vous importer la configuration ?"
    echo ""
    echo "  1) Coller la configuration manuellement"
    echo "  2) Importer depuis un fichier .conf"
    echo ""
    echo "  q) Retour au menu"
    echo ""
    read -p "Choix : " import_choice

    case $import_choice in
        1) import_config_paste ;;
        2) import_config_file ;;
        q|Q) show_menu ;;
        *) 
            print_error "Choix invalide."
            sleep 1
            import_client_config
            ;;
    esac
}

import_config_paste() {
    clear
    print_header "     Coller la configuration WireGuard"

    # Vérifier que nano est installé
    if ! command -v nano &> /dev/null; then
        print_info "Installation de nano..."
        apt-get install -y nano
    fi

    # Demander le nom de l'interface
    echo ""
    read -p "Nom de l'interface (par défaut: wg0) : " INTERFACE_NAME
    INTERFACE_NAME=${INTERFACE_NAME:-wg0}
    
    # Vérifier si l'interface existe déjà
    if [[ -f "$WG_DIR/${INTERFACE_NAME}.conf" ]]; then
        print_warning "Une configuration pour '$INTERFACE_NAME' existe déjà."
        read -p "Voulez-vous la remplacer ? (o/N) " -n 1 -r
        echo
        if [[ ! $REPLY =~ ^[Oo]$ ]]; then
            show_menu
            return
        fi
        # Arrêter l'interface si active
        wg-quick down "$INTERFACE_NAME" 2>/dev/null || true
        systemctl stop "wg-quick@${INTERFACE_NAME}" 2>/dev/null || true
    fi

    # Créer un fichier temporaire avec un modèle
    TEMP_CONF=$(mktemp /tmp/wireguard-XXXXXX.conf)
    cat > "$TEMP_CONF" << 'TEMPLATE'
# Collez votre configuration WireGuard ci-dessous
# Supprimez ces lignes de commentaires
# Sauvegardez avec Ctrl+O, Entree, puis quittez avec Ctrl+X
#
# Exemple de configuration :
# [Interface]
# Address = 172.26.18.2/32
# PrivateKey = VOTRE_CLE_PRIVEE
# DNS = 1.1.1.1
#
# [Peer]
# PublicKey = CLE_PUBLIQUE_SERVEUR
# PresharedKey = CLE_PARTAGEE
# Endpoint = serveur.example.com:51820
# AllowedIPs = 172.26.18.1/32
# PersistentKeepalive = 25

TEMPLATE

    echo ""
    print_info "L'editeur nano va s'ouvrir."
    print_info "Collez votre configuration, puis :"
    echo "  - Ctrl+O puis Entree pour sauvegarder"
    echo "  - Ctrl+X pour quitter"
    echo ""
    echo "Appuyez sur ENTREE pour ouvrir l'editeur..."
    read -r

    # Ouvrir nano
    nano "$TEMP_CONF"

    # Vérifier que le fichier a été modifié et contient une config valide
    CONFIG_CONTENT=$(grep -v "^#" "$TEMP_CONF" | grep -v "^$" || true)

    if [[ -z "$CONFIG_CONTENT" ]]; then
        print_error "Le fichier est vide ou ne contient que des commentaires."
        rm -f "$TEMP_CONF"
        echo ""
        echo "Appuyez sur ENTREE pour revenir au menu..."
        read -r
        show_menu
        return
    fi

    if ! grep -q "\[Interface\]" "$TEMP_CONF"; then
        print_error "Configuration invalide : section [Interface] manquante."
        rm -f "$TEMP_CONF"
        echo ""
        echo "Appuyez sur ENTREE pour revenir au menu..."
        read -r
        show_menu
        return
    fi

    if ! grep -q "\[Peer\]" "$TEMP_CONF"; then
        print_error "Configuration invalide : section [Peer] manquante."
        rm -f "$TEMP_CONF"
        echo ""
        echo "Appuyez sur ENTREE pour revenir au menu..."
        read -r
        show_menu
        return
    fi

    # Nettoyer les commentaires d'exemple et sauvegarder
    grep -v "^#" "$TEMP_CONF" > "$WG_DIR/${INTERFACE_NAME}.conf"
    chmod 600 "$WG_DIR/${INTERFACE_NAME}.conf"
    rm -f "$TEMP_CONF"
    
    print_success "Configuration sauvegardee dans $WG_DIR/${INTERFACE_NAME}.conf"

    # Proposer d'activer le tunnel
    echo ""
    read -p "Activer le tunnel maintenant ? (O/n) " -n 1 -r
    echo
    if [[ ! $REPLY =~ ^[Nn]$ ]]; then
        activate_client_tunnel "$INTERFACE_NAME"
    else
        echo ""
        print_info "Pour activer le tunnel plus tard :"
        echo "  sudo wg-quick up $INTERFACE_NAME"
        echo ""
        print_info "Pour l'activer au demarrage :"
        echo "  sudo systemctl enable wg-quick@${INTERFACE_NAME}"
    fi

    echo ""
    echo "Appuyez sur ENTREE pour revenir au menu..."
    read -r
    show_menu
}

import_config_file() {
    clear
    print_header "      Importer depuis un fichier .conf"

    echo ""
    print_info "Entrez le chemin complet vers le fichier de configuration."
    print_info "Exemple : /tmp/client.conf ou /home/user/wireguard.conf"
    echo ""
    read -p "Chemin du fichier : " CONFIG_FILE

    if [[ ! -f "$CONFIG_FILE" ]]; then
        print_error "Fichier non trouvé : $CONFIG_FILE"
        echo ""
        echo "Appuyez sur ENTRÉE pour revenir au menu..."
        read -r
        show_menu
        return
    fi

    # Vérifier que c'est une config valide
    if ! grep -q "\[Interface\]" "$CONFIG_FILE"; then
        print_error "Fichier invalide : section [Interface] manquante."
        echo ""
        echo "Appuyez sur ENTRÉE pour revenir au menu..."
        read -r
        show_menu
        return
    fi

    # Demander le nom de l'interface
    DEFAULT_NAME=$(basename "$CONFIG_FILE" .conf)
    echo ""
    read -p "Nom de l'interface (par défaut: $DEFAULT_NAME) : " INTERFACE_NAME
    INTERFACE_NAME=${INTERFACE_NAME:-$DEFAULT_NAME}

    # Vérifier si l'interface existe déjà
    if [[ -f "$WG_DIR/${INTERFACE_NAME}.conf" ]]; then
        print_warning "Une configuration pour '$INTERFACE_NAME' existe déjà."
        read -p "Voulez-vous la remplacer ? (o/N) " -n 1 -r
        echo
        if [[ ! $REPLY =~ ^[Oo]$ ]]; then
            show_menu
            return
        fi
        # Arrêter l'interface si active
        wg-quick down "$INTERFACE_NAME" 2>/dev/null || true
        systemctl stop "wg-quick@${INTERFACE_NAME}" 2>/dev/null || true
    fi

    # Copier la configuration
    cp "$CONFIG_FILE" "$WG_DIR/${INTERFACE_NAME}.conf"
    chmod 600 "$WG_DIR/${INTERFACE_NAME}.conf"
    
    print_success "Configuration importée dans $WG_DIR/${INTERFACE_NAME}.conf"

    # Proposer d'activer le tunnel
    echo ""
    read -p "Activer le tunnel maintenant ? (O/n) " -n 1 -r
    echo
    if [[ ! $REPLY =~ ^[Nn]$ ]]; then
        activate_client_tunnel "$INTERFACE_NAME"
    else
        echo ""
        print_info "Pour activer le tunnel plus tard :"
        echo "  sudo wg-quick up $INTERFACE_NAME"
        echo ""
        echo "Pour l'activer au démarrage :"
        echo "  sudo systemctl enable wg-quick@${INTERFACE_NAME}"
    fi

    echo ""
    echo "Appuyez sur ENTRÉE pour revenir au menu..."
    read -r
    show_menu
}

activate_client_tunnel() {
    local INTERFACE_NAME="$1"
    
    print_info "Activation du tunnel $INTERFACE_NAME..."
    
    if wg-quick up "$INTERFACE_NAME" 2>&1; then
        print_success "Tunnel $INTERFACE_NAME activé !"
        echo ""
        wg show "$INTERFACE_NAME"
        
        # Proposer l'activation au démarrage
        echo ""
        read -p "Activer le tunnel au démarrage du système ? (O/n) " -n 1 -r
        echo
        if [[ ! $REPLY =~ ^[Nn]$ ]]; then
            systemctl enable "wg-quick@${INTERFACE_NAME}" 2>/dev/null
            print_success "Tunnel activé au démarrage."
        fi
    else
        print_error "Échec de l'activation du tunnel."
        print_info "Vérifiez la configuration dans $WG_DIR/${INTERFACE_NAME}.conf"
    fi
}

# === Gestion des tunnels clients ===

manage_client_tunnels() {
    clear
    print_header "          Gestion des tunnels clients"

    # Lister les configurations disponibles
    CONFIGS=$(find "$WG_DIR" -maxdepth 1 -name "*.conf" -type f 2>/dev/null | grep -v "wg0.conf" || true)
    
    # Inclure wg0.conf s'il ne contient pas de section [Peer] avec AllowedIPs contenant plusieurs IPs (= config serveur)
    if [[ -f "$WG_DIR/wg0.conf" ]]; then
        # Si wg0.conf a PostUp avec iptables, c'est une config serveur
        if ! grep -q "PostUp.*iptables" "$WG_DIR/wg0.conf" 2>/dev/null; then
            CONFIGS="$WG_DIR/wg0.conf"$'\n'"$CONFIGS"
        fi
    fi

    if [[ -z "$CONFIGS" ]]; then
        print_warning "Aucune configuration client trouvée."
        print_info "Utilisez 'Importer une configuration client' pour en ajouter une."
        echo ""
        echo "Appuyez sur ENTRÉE pour revenir au menu..."
        read -r
        show_menu
        return
    fi

    echo ""
    print_info "Tunnels configurés :"
    echo ""
    
    i=1
    declare -A TUNNEL_MAP
    while IFS= read -r conf; do
        [[ -z "$conf" ]] && continue
        IFACE=$(basename "$conf" .conf)
        
        # Vérifier si actif
        if wg show "$IFACE" &>/dev/null; then
            STATUS="${GREEN}[ACTIF]${NC}"
        else
            STATUS="${RED}[INACTIF]${NC}"
        fi
        
        # Vérifier si activé au démarrage
        if systemctl is-enabled "wg-quick@${IFACE}" &>/dev/null; then
            BOOT="${YELLOW}[auto]${NC}"
        else
            BOOT=""
        fi
        
        echo -e "  $i) $IFACE $STATUS $BOOT"
        TUNNEL_MAP[$i]="$IFACE"
        ((i++))
    done <<< "$CONFIGS"

    echo ""
    echo "  a) Activer un tunnel"
    echo "  d) Désactiver un tunnel"
    echo "  s) Supprimer une configuration"
    echo ""
    echo "  q) Retour au menu"
    echo ""
    read -p "Action : " action

    case $action in
        a)
            read -p "Numéro du tunnel à activer : " num
            IFACE="${TUNNEL_MAP[$num]}"
            if [[ -n "$IFACE" ]]; then
                wg-quick up "$IFACE" 2>/dev/null && print_success "Tunnel $IFACE activé." || print_error "Échec."
                sleep 2
            fi
            manage_client_tunnels
            ;;
        d)
            read -p "Numéro du tunnel à désactiver : " num
            IFACE="${TUNNEL_MAP[$num]}"
            if [[ -n "$IFACE" ]]; then
                wg-quick down "$IFACE" 2>/dev/null && print_success "Tunnel $IFACE désactivé." || print_error "Échec."
                sleep 2
            fi
            manage_client_tunnels
            ;;
        s)
            read -p "Numéro de la configuration à supprimer : " num
            IFACE="${TUNNEL_MAP[$num]}"
            if [[ -n "$IFACE" ]]; then
                echo -e "${RED}Supprimer la configuration $IFACE ?${NC}"
                read -p "Confirmer (o/N) : " -n 1 -r
                echo
                if [[ $REPLY =~ ^[Oo]$ ]]; then
                    wg-quick down "$IFACE" 2>/dev/null || true
                    systemctl disable "wg-quick@${IFACE}" 2>/dev/null || true
                    rm -f "$WG_DIR/${IFACE}.conf"
                    print_success "Configuration $IFACE supprimée."
                    sleep 2
                fi
            fi
            manage_client_tunnels
            ;;
        q|Q) show_menu ;;
        *) manage_client_tunnels ;;
    esac
}

# === Fonction d'installation serveur ===

install_wireguard() {
    clear
    print_header "         Installation de WireGuard sur Debian 13"

    # Vérifier si déjà installé
    if command -v wg &> /dev/null && [[ -f "$WG_CONF" ]]; then
        print_warning "WireGuard est déjà installé et configuré."
        read -p "Voulez-vous réinstaller ? (o/N) " -n 1 -r
        echo
        if [[ ! $REPLY =~ ^[Oo]$ ]]; then
            show_menu
            return
        fi
        # Arrêter WireGuard si actif
        wg-quick down wg0 2>/dev/null || true
        systemctl stop wg-quick@wg0 2>/dev/null || true
    fi

    # === Étape 1 : Mise à jour et installation des paquets ===
    print_info "Mise à jour des dépôts..."
    apt-get update -qq
    print_success "Dépôts mis à jour."

    print_info "Installation de WireGuard et des outils..."
    apt-get install -y wireguard wireguard-tools iptables qrencode curl
    print_success "Paquets WireGuard installés."

    # Vérification
    if ! command -v wg &> /dev/null; then
        print_error "Échec de l'installation de WireGuard."
        exit 1
    fi
    print_info "Version WireGuard : $(wg --version)"

    # === Étape 2 : Activer IP forwarding ===
    print_info "Activation du routage IP..."
    
    # Activer immédiatement
    sysctl -w net.ipv4.ip_forward=1 > /dev/null
    
    # Rendre persistant via sysctl.d (plus propre que sysctl.conf)
    echo "net.ipv4.ip_forward=1" > /etc/sysctl.d/99-wireguard.conf
    print_success "Routage IP activé."

    # === Étape 3 : Répertoire de configuration ===
    print_info "Configuration du répertoire WireGuard..."
    mkdir -p "$WG_DIR"
    chmod 700 "$WG_DIR"
    print_success "Répertoire $WG_DIR prêt."

    # === Étape 4 : Génération des clés serveur ===
    print_info "Génération des clés du serveur..."
    cd "$WG_DIR"
    umask 077
    wg genkey | tee server_private.key | wg pubkey > server_public.key
    chmod 600 "$WG_DIR"/*.key
    
    SERVER_PRIVATE=$(cat server_private.key)
    SERVER_PUBLIC=$(cat server_public.key)
    
    print_success "Clés du serveur générées."
    echo -e "  Clé publique du serveur : ${YELLOW}$SERVER_PUBLIC${NC}"

    # Détecter l'interface principale
    MAIN_IF=$(get_main_interface)
    if [[ -z "$MAIN_IF" ]]; then
        print_warning "Impossible de détecter l'interface principale."
        read -p "Nom de l'interface réseau principale (ex: eth0, ens3) : " MAIN_IF
    fi
    print_info "Interface principale détectée : $MAIN_IF"

    # === Étape 5 : Configuration wg0.conf ===
    print_info "Création de la configuration WireGuard..."
    
    cat > "$WG_CONF" << EOF
[Interface]
Address = ${WG_SERVER_IP}${WG_MASK}
PrivateKey = ${SERVER_PRIVATE}
ListenPort = ${WG_PORT}
SaveConfig = false

# Règles iptables - Isolation des clients (accès serveur uniquement)
PostUp = iptables -A FORWARD -i wg0 -o wg0 -j DROP
PostUp = iptables -A FORWARD -i wg0 -o ${MAIN_IF} -j DROP
PostUp = iptables -A INPUT -i wg0 -s ${WG_SUBNET}.0${WG_MASK} -d ${WG_SERVER_IP} -j ACCEPT
PostUp = iptables -A INPUT -i wg0 -j DROP
PostUp = iptables -A OUTPUT -o wg0 -j ACCEPT

PostDown = iptables -D FORWARD -i wg0 -o wg0 -j DROP 2>/dev/null || true
PostDown = iptables -D FORWARD -i wg0 -o ${MAIN_IF} -j DROP 2>/dev/null || true
PostDown = iptables -D INPUT -i wg0 -s ${WG_SUBNET}.0${WG_MASK} -d ${WG_SERVER_IP} -j ACCEPT 2>/dev/null || true
PostDown = iptables -D INPUT -i wg0 -j DROP 2>/dev/null || true
PostDown = iptables -D OUTPUT -o wg0 -j ACCEPT 2>/dev/null || true
EOF
    
    chmod 600 "$WG_CONF"
    print_success "Configuration wg0.conf créée."

    # === Étape 6 : Ouverture du port dans le pare-feu ===
    print_info "Configuration du pare-feu..."
    
    # Ouvrir le port UDP WireGuard
    if command -v ufw &> /dev/null && ufw status | grep -q "active"; then
        ufw allow ${WG_PORT}/udp
        print_success "Port ${WG_PORT}/udp ouvert (ufw)."
    elif command -v firewall-cmd &> /dev/null; then
        firewall-cmd --permanent --add-port=${WG_PORT}/udp
        firewall-cmd --reload
        print_success "Port ${WG_PORT}/udp ouvert (firewalld)."
    else
        print_warning "Aucun pare-feu détecté (ufw/firewalld)."
        print_info "Assurez-vous que le port ${WG_PORT}/udp est accessible."
    fi

    # === Étape 7 : Activation du service systemd ===
    print_info "Activation du service WireGuard..."
    systemctl enable wg-quick@wg0
    print_success "Service wg-quick@wg0 activé au démarrage."

    # === Étape 8 : Démarrage ===
    print_info "Démarrage de WireGuard..."
    systemctl start wg-quick@wg0
    
    echo ""
    print_success "WireGuard est installé et actif !"
    echo ""
    print_info "État du serveur :"
    wg show
    
    echo ""
    print_info "Pour ajouter un client, relancez ce script et choisissez l'option 2."
    echo ""
    echo "Appuyez sur ENTRÉE pour revenir au menu..."
    read -r
    show_menu
}

# === Fonction d'ajout de client ===

add_client() {
    clear
    print_header "         Ajout d'un nouveau client WireGuard"

    # Vérifications préalables
    if ! command -v wg &> /dev/null; then
        print_error "WireGuard n'est pas installé."
        print_info "Lancez d'abord l'installation (option 1)."
        echo ""
        echo "Appuyez sur ENTRÉE pour revenir au menu..."
        read -r
        show_menu
        return
    fi

    if [[ ! -f "$WG_CONF" ]]; then
        print_error "Configuration WireGuard non trouvée."
        print_info "Lancez d'abord l'installation (option 1)."
        echo ""
        echo "Appuyez sur ENTRÉE pour revenir au menu..."
        read -r
        show_menu
        return
    fi

    # Récupérer la clé publique du serveur
    if [[ ! -f "$WG_DIR/server_public.key" ]]; then
        print_error "Clé publique du serveur non trouvée."
        exit 1
    fi
    SERVER_PUBLIC=$(cat "$WG_DIR/server_public.key")

    # Demander le nom du client
    echo ""
    read -p "Nom du client (ex: laptop-bureau, iphone-jean) : " CLIENT_NAME
    
    if [[ -z "$CLIENT_NAME" ]]; then
        print_error "Le nom du client ne peut pas être vide."
        echo ""
        echo "Appuyez sur ENTRÉE pour revenir au menu..."
        read -r
        show_menu
        return
    fi
    
    # Nettoyer le nom (remplacer espaces par tirets, minuscules)
    CLIENT_NAME=$(echo "$CLIENT_NAME" | tr ' ' '-' | tr '[:upper:]' '[:lower:]')
    
    # Vérifier si le client existe déjà
    if [[ -f "$WG_DIR/${CLIENT_NAME}_private.key" ]]; then
        print_error "Un client nommé '$CLIENT_NAME' existe déjà."
        echo ""
        echo "Appuyez sur ENTRÉE pour revenir au menu..."
        read -r
        show_menu
        return
    fi

    # Afficher les IPs déjà utilisées
    echo ""
    print_info "Sous-réseau VPN : ${WG_SUBNET}.0${WG_MASK}"
    print_info "IP du serveur   : ${WG_SERVER_IP}"
    echo ""
    
    # Lister les IPs déjà attribuées
    USED_IPS=$(grep -E "AllowedIPs\s*=" "$WG_CONF" 2>/dev/null | grep -oE "${WG_SUBNET}\.[0-9]+" | sort -t. -k4 -n || true)
    if [[ -n "$USED_IPS" ]]; then
        print_info "IPs clients déjà attribuées :"
        echo "$USED_IPS" | while read -r ip; do
            echo "  - $ip"
        done
    fi
    
    # Suggérer la prochaine IP disponible
    LAST_OCTET=1
    for i in $(seq 2 14); do
        if ! echo "$USED_IPS" | grep -q "${WG_SUBNET}.$i"; then
            LAST_OCTET=$i
            break
        fi
    done
    SUGGESTED_IP="${WG_SUBNET}.${LAST_OCTET}"
    
    echo ""
    read -p "IP du client [$SUGGESTED_IP] : " CLIENT_IP
    CLIENT_IP=${CLIENT_IP:-$SUGGESTED_IP}

    # Valider l'IP
    if [[ ! $CLIENT_IP =~ ^${WG_SUBNET}\.[0-9]+$ ]]; then
        print_error "L'IP doit être dans le sous-réseau ${WG_SUBNET}.0${WG_MASK}"
        echo ""
        echo "Appuyez sur ENTRÉE pour revenir au menu..."
        read -r
        show_menu
        return
    fi
    
    CLIENT_OCTET=$(echo "$CLIENT_IP" | cut -d. -f4)
    if [[ $CLIENT_OCTET -lt 2 ]] || [[ $CLIENT_OCTET -gt 14 ]]; then
        print_error "Le dernier octet doit être entre 2 et 14 (1 = serveur, 15 = broadcast)."
        echo ""
        echo "Appuyez sur ENTRÉE pour revenir au menu..."
        read -r
        show_menu
        return
    fi
    
    if echo "$USED_IPS" | grep -q "^${CLIENT_IP}$"; then
        print_error "L'IP $CLIENT_IP est déjà utilisée par un autre client."
        echo ""
        echo "Appuyez sur ENTRÉE pour revenir au menu..."
        read -r
        show_menu
        return
    fi

    # Demander l'endpoint du serveur
    echo ""
    print_info "L'endpoint est l'IP publique ou le nom de domaine du serveur WireGuard."
    
    # Tenter de récupérer l'IP publique
    PUBLIC_IP=$(curl -4 -s --connect-timeout 5 ifconfig.me 2>/dev/null || echo "")
    if [[ -n "$PUBLIC_IP" ]]; then
        print_info "IP publique détectée : $PUBLIC_IP"
    fi
    
    # Récupérer l'IP locale
    LOCAL_IP=$(hostname -I 2>/dev/null | awk '{print $1}' || echo "")
    if [[ -n "$LOCAL_IP" ]]; then
        print_info "IP locale           : $LOCAL_IP"
    fi
    
    echo ""
    DEFAULT_ENDPOINT=${PUBLIC_IP:-$LOCAL_IP}
    read -p "Endpoint du serveur (IP ou domaine) [$DEFAULT_ENDPOINT] : " SERVER_ENDPOINT
    SERVER_ENDPOINT=${SERVER_ENDPOINT:-$DEFAULT_ENDPOINT}

    if [[ -z "$SERVER_ENDPOINT" ]]; then
        print_error "L'endpoint du serveur est requis."
        echo ""
        echo "Appuyez sur ENTRÉE pour revenir au menu..."
        read -r
        show_menu
        return
    fi

    # === Génération des clés du client ===
    print_info "Génération des clés pour '$CLIENT_NAME'..."
    cd "$WG_DIR"
    umask 077
    
    wg genkey | tee "${CLIENT_NAME}_private.key" | wg pubkey > "${CLIENT_NAME}_public.key"
    wg genpsk > "${CLIENT_NAME}_psk.key"
    chmod 600 "$WG_DIR"/*.key
    
    CLIENT_PRIVATE=$(cat "${CLIENT_NAME}_private.key")
    CLIENT_PUBLIC=$(cat "${CLIENT_NAME}_public.key")
    CLIENT_PSK=$(cat "${CLIENT_NAME}_psk.key")
    
    print_success "Clés du client générées."

    # === Ajout du peer dans wg0.conf ===
    print_info "Ajout du client à la configuration du serveur..."
    
    cat >> "$WG_CONF" << EOF

[Peer]
# ${CLIENT_NAME}
PublicKey = ${CLIENT_PUBLIC}
PresharedKey = ${CLIENT_PSK}
AllowedIPs = ${CLIENT_IP}/32
EOF
    
    print_success "Client ajouté à wg0.conf."

    # === Rechargement de la configuration ===
    if wg show wg0 &> /dev/null; then
        print_info "Rechargement de la configuration WireGuard..."
        wg syncconf wg0 <(wg-quick strip wg0)
        print_success "Configuration rechargée."
    else
        print_warning "WireGuard n'est pas actif. Démarrez-le avec l'option 4."
    fi

    # === Création de la configuration client ===
    CLIENT_CONF_FILE="$WG_DIR/clients/${CLIENT_NAME}.conf"
    mkdir -p "$WG_DIR/clients"
    
    cat > "$CLIENT_CONF_FILE" << EOF
[Interface]
Address = ${CLIENT_IP}/32
PrivateKey = ${CLIENT_PRIVATE}
DNS = 1.1.1.1

[Peer]
PublicKey = ${SERVER_PUBLIC}
PresharedKey = ${CLIENT_PSK}
Endpoint = ${SERVER_ENDPOINT}:${WG_PORT}
AllowedIPs = ${WG_SERVER_IP}/32
PersistentKeepalive = 25
EOF
    chmod 600 "$CLIENT_CONF_FILE"

    # === Affichage de la configuration client ===
    clear
    print_header "    Configuration pour le client '$CLIENT_NAME'"
    
    echo -e "${YELLOW}Copiez cette configuration dans l'application WireGuard du client :${NC}"
    echo ""
    echo "─────────────────────────────────────────────────────────────"
    echo
    cat "$CLIENT_CONF_FILE"
    echo
    echo "─────────────────────────────────────────────────────────────"
    echo ""
    
    print_success "Configuration sauvegardée dans : $CLIENT_CONF_FILE"
    
    # Générer le QR code si qrencode est disponible
    if command -v qrencode &> /dev/null; then
        echo ""
        print_info "QR Code pour import mobile :"
        echo ""
        qrencode -t ANSIUTF8 < "$CLIENT_CONF_FILE"
    fi
    
    echo ""
    print_info "État actuel du serveur :"
    wg show
    echo ""
    echo "Appuyez sur ENTRÉE pour revenir au menu..."
    read -r
    show_menu
}

# === Fonction de suppression de client ===

remove_client() {
    clear
    print_header "         Suppression d'un client WireGuard"

    if [[ ! -f "$WG_CONF" ]]; then
        print_error "Configuration WireGuard non trouvée."
        echo ""
        echo "Appuyez sur ENTRÉE pour revenir au menu..."
        read -r
        show_menu
        return
    fi

    # Lister les clients existants
    echo ""
    print_info "Clients configurés :"
    echo ""
    
    CLIENTS=$(grep -E "^#\s+\S+" "$WG_CONF" | sed 's/^#\s*//' | grep -v "Règles" || true)
    
    if [[ -z "$CLIENTS" ]]; then
        print_warning "Aucun client configuré."
        echo ""
        echo "Appuyez sur ENTRÉE pour revenir au menu..."
        read -r
        show_menu
        return
    fi
    
    i=1
    declare -A CLIENT_MAP
    while read -r client; do
        echo "  $i) $client"
        CLIENT_MAP[$i]="$client"
        ((i++))
    done <<< "$CLIENTS"
    
    echo ""
    read -p "Numéro du client à supprimer (ou q pour annuler) : " choice
    
    if [[ "$choice" == "q" ]] || [[ "$choice" == "Q" ]]; then
        show_menu
        return
    fi
    
    CLIENT_NAME="${CLIENT_MAP[$choice]}"
    if [[ -z "$CLIENT_NAME" ]]; then
        print_error "Choix invalide."
        echo ""
        echo "Appuyez sur ENTRÉE pour revenir au menu..."
        read -r
        show_menu
        return
    fi
    
    echo ""
    echo -e "${RED}Vous allez supprimer le client : $CLIENT_NAME${NC}"
    read -p "Confirmer ? (o/N) " -n 1 -r
    echo
    
    if [[ ! $REPLY =~ ^[Oo]$ ]]; then
        print_info "Suppression annulée."
        sleep 2
        show_menu
        return
    fi
    
    # Récupérer la clé publique du client pour la supprimer avec wg
    if [[ -f "$WG_DIR/${CLIENT_NAME}_public.key" ]]; then
        CLIENT_PUBKEY=$(cat "$WG_DIR/${CLIENT_NAME}_public.key")
        # Supprimer le peer de l'interface active
        if wg show wg0 &> /dev/null; then
            wg set wg0 peer "$CLIENT_PUBKEY" remove 2>/dev/null || true
        fi
    fi
    
    # Supprimer le bloc [Peer] du fichier de configuration
    # On cherche le commentaire avec le nom du client et on supprime jusqu'au prochain [Peer] ou fin de fichier
    print_info "Suppression du client de wg0.conf..."
    
    # Créer une copie temporaire
    TEMP_CONF=$(mktemp)
    awk -v client="$CLIENT_NAME" '
        BEGIN { skip=0 }
        /^# / && $2 == client { skip=1; next }
        /^\[Peer\]/ && skip { skip=0 }
        /^\[Peer\]/ { if(skip) skip=0 }
        skip && /^\[/ { skip=0 }
        !skip { print }
    ' "$WG_CONF" > "$TEMP_CONF"
    
    # Supprimer le bloc [Peer] précédant le commentaire
    awk '
        BEGIN { buffer="" }
        /^\[Peer\]/ { buffer=$0; next }
        buffer != "" && /^#/ { 
            if (buffer != "") print buffer
            buffer=""
            print
            next
        }
        buffer != "" { 
            print buffer
            buffer=""
            print
            next
        }
        { print }
    ' "$TEMP_CONF" > "${TEMP_CONF}.2"
    
    # Nettoyer les lignes vides multiples et restaurer
    sed '/^$/N;/^\n$/d' "${TEMP_CONF}.2" > "$WG_CONF"
    rm -f "$TEMP_CONF" "${TEMP_CONF}.2"
    
    # Supprimer les fichiers de clés
    rm -f "$WG_DIR/${CLIENT_NAME}_private.key"
    rm -f "$WG_DIR/${CLIENT_NAME}_public.key"
    rm -f "$WG_DIR/${CLIENT_NAME}_psk.key"
    rm -f "$WG_DIR/clients/${CLIENT_NAME}.conf"
    
    print_success "Client '$CLIENT_NAME' supprimé."
    
    echo ""
    echo "Appuyez sur ENTRÉE pour revenir au menu..."
    read -r
    show_menu
}

# === Fonction de désinstallation ===

uninstall_wireguard() {
    clear
    print_header "            Désinstallation de WireGuard"
    
    echo -e "${RED}Cette opération va :${NC}"
    echo "  - Arrêter WireGuard"
    echo "  - Désactiver le service systemd"
    echo "  - Supprimer les règles iptables"
    echo "  - Supprimer toutes les clés et configurations"
    echo "  - Désinstaller les paquets wireguard"
    echo ""
    read -p "Êtes-vous sûr de vouloir continuer ? (o/N) " -n 1 -r
    echo
    
    if [[ ! $REPLY =~ ^[Oo]$ ]]; then
        print_info "Désinstallation annulée."
        sleep 2
        show_menu
        return
    fi
    
    echo ""
    
    # 1. Arrêter WireGuard
    print_info "Arrêt de WireGuard..."
    systemctl stop wg-quick@wg0 2>/dev/null && print_success "Service WireGuard arrêté." || print_warning "Service WireGuard n'était pas actif."
    wg-quick down wg0 2>/dev/null || true
    
    # 2. Désactiver le service
    print_info "Désactivation du service systemd..."
    systemctl disable wg-quick@wg0 2>/dev/null && print_success "Service désactivé." || print_warning "Service déjà désactivé."
    
    # 3. Supprimer le répertoire de configuration
    if [[ -d "$WG_DIR" ]]; then
        print_info "Suppression du répertoire de configuration..."
        rm -rf "$WG_DIR"
        print_success "Répertoire $WG_DIR supprimé."
    else
        print_warning "Répertoire $WG_DIR non trouvé."
    fi
    
    # 4. Désinstaller les paquets
    print_info "Désinstallation des paquets WireGuard..."
    apt-get remove -y wireguard wireguard-tools 2>/dev/null && print_success "Paquets WireGuard désinstallés." || print_warning "Paquets non trouvés."
    apt-get autoremove -y
    
    # 5. Optionnel : désactiver IP forwarding
    echo ""
    read -p "Désactiver le routage IP (net.ipv4.ip_forward) ? (o/N) " -n 1 -r
    echo
    if [[ $REPLY =~ ^[Oo]$ ]]; then
        sysctl -w net.ipv4.ip_forward=0 > /dev/null
        rm -f /etc/sysctl.d/99-wireguard.conf
        print_success "Routage IP désactivé."
    fi
    
    echo ""
    print_success "Désinstallation terminée !"
    echo ""
    echo "Appuyez sur ENTRÉE pour quitter..."
    read -r
    exit 0
}

# === Fonction lister les clients ===

list_clients() {
    clear
    print_header "            Clients WireGuard configurés"
    
    if [[ ! -f "$WG_CONF" ]]; then
        print_warning "Aucune configuration WireGuard trouvée."
        echo ""
        echo "Appuyez sur ENTRÉE pour revenir au menu..."
        read -r
        show_menu
        return
    fi
    
    echo ""
    
    # Extraire les clients avec leurs IPs
    FOUND=0
    while IFS= read -r line; do
        if [[ "$line" =~ ^#[[:space:]]+(.+)$ ]]; then
            CLIENT_NAME="${BASH_REMATCH[1]}"
            # Ignorer les commentaires de règles iptables
            if [[ "$CLIENT_NAME" != *"Règles"* ]] && [[ "$CLIENT_NAME" != *"iptables"* ]]; then
                CURRENT_CLIENT="$CLIENT_NAME"
            fi
        elif [[ "$line" =~ AllowedIPs[[:space:]]*=[[:space:]]*([0-9.]+) ]]; then
            CLIENT_IP="${BASH_REMATCH[1]}"
            if [[ -n "$CURRENT_CLIENT" ]]; then
                echo -e "  ${GREEN}●${NC} $CURRENT_CLIENT : ${YELLOW}$CLIENT_IP${NC}"
                FOUND=1
                CURRENT_CLIENT=""
            fi
        fi
    done < "$WG_CONF"
    
    if [[ $FOUND -eq 0 ]]; then
        print_warning "Aucun client configuré."
    fi
    
    echo ""
    
    # Afficher les connexions actives
    if wg show wg0 &> /dev/null; then
        echo ""
        print_info "Connexions actives :"
        echo ""
        wg show wg0 | grep -A4 "^peer:" | while IFS= read -r line; do
            if [[ "$line" =~ "latest handshake:" ]]; then
                echo -e "    ${line}"
            elif [[ "$line" =~ "transfer:" ]]; then
                echo -e "    ${line}"
            fi
        done
    fi
    
    echo ""
    echo "Appuyez sur ENTRÉE pour revenir au menu..."
    read -r
    show_menu
}

# === Afficher la configuration d'un client ===

show_client_config() {
    clear
    print_header "       Afficher la configuration d'un client"

    if [[ ! -d "$WG_DIR/clients" ]] || [[ -z "$(ls -A $WG_DIR/clients 2>/dev/null)" ]]; then
        print_warning "Aucune configuration client sauvegardée."
        echo ""
        echo "Appuyez sur ENTRÉE pour revenir au menu..."
        read -r
        show_menu
        return
    fi
    
    echo ""
    print_info "Configurations disponibles :"
    echo ""
    
    i=1
    declare -A CONFIG_MAP
    for conf in "$WG_DIR/clients"/*.conf; do
        CLIENT_NAME=$(basename "$conf" .conf)
        echo "  $i) $CLIENT_NAME"
        CONFIG_MAP[$i]="$conf"
        ((i++))
    done
    
    echo ""
    read -p "Numéro de la configuration à afficher (ou q pour annuler) : " choice
    
    if [[ "$choice" == "q" ]] || [[ "$choice" == "Q" ]]; then
        show_menu
        return
    fi
    
    CONF_FILE="${CONFIG_MAP[$choice]}"
    if [[ -z "$CONF_FILE" ]] || [[ ! -f "$CONF_FILE" ]]; then
        print_error "Choix invalide."
        echo ""
        echo "Appuyez sur ENTRÉE pour revenir au menu..."
        read -r
        show_menu
        return
    fi
    
    CLIENT_NAME=$(basename "$CONF_FILE" .conf)
    
    clear
    print_header "    Configuration du client '$CLIENT_NAME'"
    
    echo ""
    echo "─────────────────────────────────────────────────────────────"
    echo
    cat "$CONF_FILE"
    echo
    echo "─────────────────────────────────────────────────────────────"
    
    # Générer le QR code si qrencode est disponible
    if command -v qrencode &> /dev/null; then
        echo ""
        print_info "QR Code pour import mobile :"
        echo ""
        qrencode -t ANSIUTF8 < "$CONF_FILE"
    fi
    
    echo ""
    echo "Appuyez sur ENTRÉE pour revenir au menu..."
    read -r
    show_menu
}

# === Menu principal ===

show_menu() {
    clear
    print_header "           WireGuard Manager pour Debian 13"
    
    echo -e "  ${CYAN}── Serveur ──${NC}"
    echo "  1) Installer WireGuard (serveur)"
    echo "  2) Ajouter un client"
    echo "  3) Afficher l'état du serveur"
    echo "  4) Démarrer WireGuard (serveur)"
    echo "  5) Arrêter WireGuard (serveur)"
    echo "  6) Lister les clients configurés"
    echo "  7) Afficher la config d'un client (+ QR code)"
    echo "  8) Supprimer un client"
    echo ""
    echo -e "  ${CYAN}── Client ──${NC}"
    echo "  10) Installer WireGuard (client)"
    echo "  11) Importer une configuration client"
    echo "  12) Gérer les tunnels clients"
    echo ""
    echo -e "  ${RED}9) Désinstaller WireGuard${NC}"
    echo ""
    echo "  q) Quitter"
    echo ""
    read -p "Choix : " choice
    
    case $choice in
        1) install_wireguard ;;
        2) add_client ;;
        3) 
            clear
            print_header "              État du serveur WireGuard"
            echo ""
            if wg show wg0 &> /dev/null; then
                wg show
                echo ""
                print_info "Service systemd :"
                systemctl status wg-quick@wg0 --no-pager -l 2>/dev/null | head -5 || true
            else
                print_warning "WireGuard n'est pas actif."
            fi
            echo ""
            echo "Appuyez sur ENTRÉE pour revenir au menu..."
            read -r
            show_menu
            ;;
        4) 
            systemctl start wg-quick@wg0 && print_success "WireGuard démarré." || print_error "Échec du démarrage."
            sleep 2
            show_menu
            ;;
        5) 
            systemctl stop wg-quick@wg0 && print_success "WireGuard arrêté." || print_error "Échec de l'arrêt."
            sleep 2
            show_menu
            ;;
        6) list_clients ;;
        7) show_client_config ;;
        8) remove_client ;;
        9) uninstall_wireguard ;;
        10) install_wireguard_client ;;
        11) import_client_config ;;
        12) manage_client_tunnels ;;
        q|Q) 
            echo ""
            print_info "Au revoir !"
            exit 0 
            ;;
        *) 
            print_error "Choix invalide." 
            sleep 1
            show_menu
            ;;
    esac
}

# === Point d'entrée ===

check_root
show_menu
