#!/bin/bash

#===============================================================================
# Script: manage-unattended-upgrades.sh
# Description: Installation, configuration et désinstallation de unattended-upgrades
# Compatibilité: Debian, Ubuntu, Linux Mint
# Usage: sudo ./manage-unattended-upgrades.sh [install|uninstall|status]
#===============================================================================

set -e

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

# Fichiers de configuration
AUTO_UPGRADES_FILE="/etc/apt/apt.conf.d/20auto-upgrades"
UNATTENDED_UPGRADES_FILE="/etc/apt/apt.conf.d/50unattended-upgrades"
BACKUP_DIR="/root/unattended-upgrades-backup"

#-------------------------------------------------------------------------------
# Fonctions utilitaires
#-------------------------------------------------------------------------------

print_header() {
    echo -e "\n${BLUE}============================================${NC}"
    echo -e "${BLUE}  $1${NC}"
    echo -e "${BLUE}============================================${NC}\n"
}

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

print_warning() {
    echo -e "${YELLOW}[!]${NC} $1"
}

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

print_info() {
    echo -e "${BLUE}[i]${NC} $1"
}

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

check_debian_based() {
    if ! command -v apt &> /dev/null; then
        print_error "Ce script est conçu pour les distributions basées sur Debian (apt)"
        exit 1
    fi
}

get_distro_info() {
    if [[ -f /etc/os-release ]]; then
        . /etc/os-release
        DISTRO_ID="$ID"
        DISTRO_CODENAME="$VERSION_CODENAME"
        DISTRO_NAME="$PRETTY_NAME"
    else
        print_error "Impossible de détecter la distribution"
        exit 1
    fi
}

#-------------------------------------------------------------------------------
# Fonction d'installation
#-------------------------------------------------------------------------------

install_unattended_upgrades() {
    print_header "Installation de Unattended-Upgrades"
    
    get_distro_info
    print_info "Distribution détectée: $DISTRO_NAME"
    print_info "Codename: $DISTRO_CODENAME"
    
    # Installation des paquets
    echo ""
    print_info "Installation des paquets nécessaires..."
    apt update -qq
    apt install -y unattended-upgrades apt-listchanges
    print_success "Paquets installés"
    
    # Sauvegarde des fichiers existants
    if [[ -f "$UNATTENDED_UPGRADES_FILE" ]]; then
        mkdir -p "$BACKUP_DIR"
        cp "$UNATTENDED_UPGRADES_FILE" "$BACKUP_DIR/50unattended-upgrades.backup.$(date +%Y%m%d%H%M%S)"
        print_info "Sauvegarde de la configuration existante effectuée"
    fi
    
    # Questions de configuration
    echo ""
    print_header "Configuration"
    
    # Type de mises à jour
    echo "Quelles mises à jour souhaitez-vous automatiser ?"
    echo "  1) Sécurité uniquement (recommandé pour production)"
    echo "  2) Sécurité + mises à jour standards"
    echo "  3) Tout (sécurité + updates + backports)"
    read -p "Votre choix [1-3] (défaut: 1): " UPDATE_CHOICE
    UPDATE_CHOICE=${UPDATE_CHOICE:-1}
    
    # Redémarrage automatique
    echo ""
    read -p "Autoriser le redémarrage automatique si nécessaire ? [o/N]: " AUTO_REBOOT
    AUTO_REBOOT=${AUTO_REBOOT:-n}
    
    if [[ "$AUTO_REBOOT" =~ ^[oOyY]$ ]]; then
        read -p "Heure du redémarrage (format HH:MM, défaut: 02:00): " REBOOT_TIME
        REBOOT_TIME=${REBOOT_TIME:-02:00}
    fi
    
    # Notification email
    echo ""
    read -p "Recevoir des notifications par email ? [o/N]: " EMAIL_NOTIFY
    EMAIL_NOTIFY=${EMAIL_NOTIFY:-n}
    
    if [[ "$EMAIL_NOTIFY" =~ ^[oOyY]$ ]]; then
        read -p "Adresse email: " EMAIL_ADDRESS
        read -p "Envoyer uniquement en cas d'erreur ? [O/n]: " EMAIL_ERROR_ONLY
        EMAIL_ERROR_ONLY=${EMAIL_ERROR_ONLY:-o}
    fi
    
    # Nettoyage automatique
    echo ""
    read -p "Supprimer automatiquement les anciens noyaux inutilisés ? [O/n]: " AUTO_REMOVE
    AUTO_REMOVE=${AUTO_REMOVE:-o}
    
    # Génération de la configuration
    print_header "Génération de la configuration"
    
    # Création du fichier 20auto-upgrades
    cat > "$AUTO_UPGRADES_FILE" << 'EOF'
APT::Periodic::Update-Package-Lists "1";
APT::Periodic::Download-Upgradeable-Packages "1";
APT::Periodic::AutocleanInterval "7";
APT::Periodic::Unattended-Upgrade "1";
EOF
    print_success "Fichier $AUTO_UPGRADES_FILE créé"
    
    # Création du fichier 50unattended-upgrades
    cat > "$UNATTENDED_UPGRADES_FILE" << EOF
// Configuration générée automatiquement le $(date)
// Distribution: $DISTRO_NAME

Unattended-Upgrade::Allowed-Origins {
    "\${distro_id}:\${distro_codename}";
    "\${distro_id}:\${distro_codename}-security";
    "\${distro_id}ESMApps:\${distro_codename}-apps-security";
    "\${distro_id}ESM:\${distro_codename}-infra-security";
EOF

    # Ajout des sources selon le choix
    if [[ "$UPDATE_CHOICE" -ge 2 ]]; then
        cat >> "$UNATTENDED_UPGRADES_FILE" << EOF
    "\${distro_id}:\${distro_codename}-updates";
EOF
    fi
    
    if [[ "$UPDATE_CHOICE" -ge 3 ]]; then
        cat >> "$UNATTENDED_UPGRADES_FILE" << EOF
    "\${distro_id}:\${distro_codename}-backports";
EOF
    fi
    
    cat >> "$UNATTENDED_UPGRADES_FILE" << EOF
};

// Liste des paquets à ne jamais mettre à jour automatiquement
Unattended-Upgrade::Package-Blacklist {
    // Exemples:
    // "libc6";
    // "libc6-dev";
    // "linux-image-*";
};

// Supprimer les dépendances inutilisées après la mise à jour
EOF

    if [[ "$AUTO_REMOVE" =~ ^[oOyY]$ ]]; then
        echo 'Unattended-Upgrade::Remove-Unused-Dependencies "true";' >> "$UNATTENDED_UPGRADES_FILE"
        echo 'Unattended-Upgrade::Remove-Unused-Kernel-Packages "true";' >> "$UNATTENDED_UPGRADES_FILE"
    else
        echo 'Unattended-Upgrade::Remove-Unused-Dependencies "false";' >> "$UNATTENDED_UPGRADES_FILE"
        echo 'Unattended-Upgrade::Remove-Unused-Kernel-Packages "false";' >> "$UNATTENDED_UPGRADES_FILE"
    fi
    
    # Configuration email
    if [[ "$EMAIL_NOTIFY" =~ ^[oOyY]$ ]] && [[ -n "$EMAIL_ADDRESS" ]]; then
        cat >> "$UNATTENDED_UPGRADES_FILE" << EOF

// Configuration email
Unattended-Upgrade::Mail "$EMAIL_ADDRESS";
EOF
        if [[ "$EMAIL_ERROR_ONLY" =~ ^[oOyY]$ ]]; then
            echo 'Unattended-Upgrade::MailReport "only-on-error";' >> "$UNATTENDED_UPGRADES_FILE"
        else
            echo 'Unattended-Upgrade::MailReport "on-change";' >> "$UNATTENDED_UPGRADES_FILE"
        fi
    fi
    
    # Configuration redémarrage
    cat >> "$UNATTENDED_UPGRADES_FILE" << EOF

// Configuration du redémarrage automatique
EOF

    if [[ "$AUTO_REBOOT" =~ ^[oOyY]$ ]]; then
        cat >> "$UNATTENDED_UPGRADES_FILE" << EOF
Unattended-Upgrade::Automatic-Reboot "true";
Unattended-Upgrade::Automatic-Reboot-Time "$REBOOT_TIME";
Unattended-Upgrade::Automatic-Reboot-WithUsers "false";
EOF
    else
        echo 'Unattended-Upgrade::Automatic-Reboot "false";' >> "$UNATTENDED_UPGRADES_FILE"
    fi
    
    # Options supplémentaires
    cat >> "$UNATTENDED_UPGRADES_FILE" << EOF

// Options supplémentaires
Unattended-Upgrade::SyslogEnable "true";
Unattended-Upgrade::SyslogFacility "daemon";
EOF

    print_success "Fichier $UNATTENDED_UPGRADES_FILE créé"
    
    # Test de la configuration
    print_header "Test de la configuration"
    print_info "Exécution d'un test (dry-run)..."
    echo ""
    
    if unattended-upgrades --dry-run --verbose 2>&1 | head -30; then
        echo ""
        print_success "Test réussi !"
    else
        print_warning "Le test a retourné des avertissements (vérifiez les logs)"
    fi
    
    # Résumé
    print_header "Installation terminée"
    echo "Résumé de la configuration:"
    echo "  - Mises à jour: $(case $UPDATE_CHOICE in 1) echo 'Sécurité uniquement';; 2) echo 'Sécurité + Updates';; 3) echo 'Tout';; esac)"
    echo "  - Redémarrage auto: $(if [[ "$AUTO_REBOOT" =~ ^[oOyY]$ ]]; then echo "Oui (à $REBOOT_TIME)"; else echo "Non"; fi)"
    echo "  - Notifications email: $(if [[ "$EMAIL_NOTIFY" =~ ^[oOyY]$ ]]; then echo "$EMAIL_ADDRESS"; else echo "Non"; fi)"
    echo "  - Nettoyage auto: $(if [[ "$AUTO_REMOVE" =~ ^[oOyY]$ ]]; then echo "Oui"; else echo "Non"; fi)"
    echo ""
    print_info "Logs disponibles: /var/log/unattended-upgrades/"
    print_info "Pour forcer une exécution: sudo unattended-upgrades --verbose"
}

#-------------------------------------------------------------------------------
# Fonction de désinstallation
#-------------------------------------------------------------------------------

uninstall_unattended_upgrades() {
    print_header "Désinstallation de Unattended-Upgrades"
    
    echo "Cette action va:"
    echo "  - Désactiver les mises à jour automatiques"
    echo "  - Supprimer les fichiers de configuration"
    echo "  - Optionnellement désinstaller les paquets"
    echo ""
    read -p "Êtes-vous sûr de vouloir continuer ? [o/N]: " CONFIRM
    
    if [[ ! "$CONFIRM" =~ ^[oOyY]$ ]]; then
        print_info "Annulation"
        exit 0
    fi
    
    # Sauvegarde avant suppression
    mkdir -p "$BACKUP_DIR"
    
    if [[ -f "$AUTO_UPGRADES_FILE" ]]; then
        cp "$AUTO_UPGRADES_FILE" "$BACKUP_DIR/20auto-upgrades.uninstall.$(date +%Y%m%d%H%M%S)"
        rm -f "$AUTO_UPGRADES_FILE"
        print_success "Fichier $AUTO_UPGRADES_FILE supprimé (sauvegarde effectuée)"
    fi
    
    if [[ -f "$UNATTENDED_UPGRADES_FILE" ]]; then
        cp "$UNATTENDED_UPGRADES_FILE" "$BACKUP_DIR/50unattended-upgrades.uninstall.$(date +%Y%m%d%H%M%S)"
        rm -f "$UNATTENDED_UPGRADES_FILE"
        print_success "Fichier $UNATTENDED_UPGRADES_FILE supprimé (sauvegarde effectuée)"
    fi
    
    # Désinstallation des paquets
    echo ""
    read -p "Désinstaller également les paquets unattended-upgrades et apt-listchanges ? [o/N]: " REMOVE_PACKAGES
    
    if [[ "$REMOVE_PACKAGES" =~ ^[oOyY]$ ]]; then
        apt remove -y unattended-upgrades apt-listchanges
        apt autoremove -y
        print_success "Paquets désinstallés"
    else
        print_info "Paquets conservés (désactivés uniquement)"
    fi
    
    print_header "Désinstallation terminée"
    print_info "Sauvegardes disponibles dans: $BACKUP_DIR"
}

#-------------------------------------------------------------------------------
# Fonction de statut
#-------------------------------------------------------------------------------

show_status() {
    print_header "Statut de Unattended-Upgrades"
    
    # Vérification de l'installation
    if dpkg -l | grep -q "^ii.*unattended-upgrades"; then
        print_success "Paquet unattended-upgrades: Installé"
        INSTALLED=true
    else
        print_warning "Paquet unattended-upgrades: Non installé"
        INSTALLED=false
    fi
    
    if [[ "$INSTALLED" == false ]]; then
        return
    fi
    
    # Vérification de l'activation
    echo ""
    if [[ -f "$AUTO_UPGRADES_FILE" ]]; then
        print_success "Fichier d'activation: Présent"
        echo "  Contenu:"
        sed 's/^/    /' "$AUTO_UPGRADES_FILE"
    else
        print_warning "Fichier d'activation: Absent (mises à jour auto désactivées)"
    fi
    
    # Configuration
    echo ""
    if [[ -f "$UNATTENDED_UPGRADES_FILE" ]]; then
        print_success "Fichier de configuration: Présent"
        
        echo ""
        echo "  Sources activées:"
        grep -E '^\s*"' "$UNATTENDED_UPGRADES_FILE" 2>/dev/null | grep -v '//' | sed 's/^/    /'
        
        echo ""
        echo "  Options importantes:"
        grep -E "^Unattended-Upgrade::(Automatic-Reboot|Mail|Remove-Unused)" "$UNATTENDED_UPGRADES_FILE" 2>/dev/null | sed 's/^/    /'
    else
        print_warning "Fichier de configuration: Absent"
    fi
    
    # Dernière exécution
    echo ""
    LOG_FILE="/var/log/unattended-upgrades/unattended-upgrades.log"
    if [[ -f "$LOG_FILE" ]]; then
        print_info "Dernières lignes du log:"
        tail -10 "$LOG_FILE" | sed 's/^/    /'
    else
        print_info "Aucun log disponible (pas encore d'exécution)"
    fi
    
    # Timer systemd
    echo ""
    print_info "Timer systemd:"
    systemctl status apt-daily-upgrade.timer --no-pager 2>/dev/null | head -5 | sed 's/^/    /' || echo "    Non disponible"
}

#-------------------------------------------------------------------------------
# Fonction d'aide
#-------------------------------------------------------------------------------

show_help() {
    echo "Usage: $0 [OPTION]"
    echo ""
    echo "Options:"
    echo "  install     Installer et configurer unattended-upgrades"
    echo "  uninstall   Désinstaller et nettoyer unattended-upgrades"
    echo "  status      Afficher le statut actuel"
    echo "  help        Afficher cette aide"
    echo ""
    echo "Sans argument, un menu interactif sera affiché."
}

#-------------------------------------------------------------------------------
# Menu interactif
#-------------------------------------------------------------------------------

interactive_menu() {
    print_header "Gestion de Unattended-Upgrades"
    
    echo "Que souhaitez-vous faire ?"
    echo ""
    echo "  1) Installer / Configurer"
    echo "  2) Désinstaller"
    echo "  3) Voir le statut"
    echo "  4) Tester la configuration (dry-run)"
    echo "  5) Forcer une exécution maintenant"
    echo "  6) Quitter"
    echo ""
    read -p "Votre choix [1-6]: " MENU_CHOICE
    
    case $MENU_CHOICE in
        1)
            install_unattended_upgrades
            ;;
        2)
            uninstall_unattended_upgrades
            ;;
        3)
            show_status
            ;;
        4)
            print_header "Test (dry-run)"
            unattended-upgrades --dry-run --verbose
            ;;
        5)
            print_header "Exécution forcée"
            print_warning "Cela va installer les mises à jour disponibles maintenant"
            read -p "Continuer ? [o/N]: " FORCE_CONFIRM
            if [[ "$FORCE_CONFIRM" =~ ^[oOyY]$ ]]; then
                unattended-upgrades --verbose
            fi
            ;;
        6)
            exit 0
            ;;
        *)
            print_error "Choix invalide"
            exit 1
            ;;
    esac
}

#-------------------------------------------------------------------------------
# Point d'entrée principal
#-------------------------------------------------------------------------------

main() {
    check_root
    check_debian_based
    
    case "${1:-}" in
        install)
            install_unattended_upgrades
            ;;
        uninstall)
            uninstall_unattended_upgrades
            ;;
        status)
            show_status
            ;;
        help|--help|-h)
            show_help
            ;;
        "")
            interactive_menu
            ;;
        *)
            print_error "Option inconnue: $1"
            show_help
            exit 1
            ;;
    esac
}

main "$@"
