#!/bin/bash

#############################
# CONFIG
#############################

# Répertoire contenant tes containers
SOURCE_DIR="/home/docker"

# Répertoire où stocker les sauvegardes
BACKUP_DIR="/home/backup/docker"

# Nombre max de backups à conserver
MAX_BACKUPS=5

# Date format
DATE="$(date +'%Y%m%d_%H%M%S')"

# Fichier TAR final
BACKUP_FILE="$BACKUP_DIR/docker_backup_${DATE}.tar.gz"

# Dossier de configs des compose à côté du TAR
CONFIG_DIR="$BACKUP_DIR/config_${DATE}"

# Dossiers à exclure (chemins relatifs à $SOURCE_DIR)
EXCLUDE_DIRS=(
    "casaos_data/*"
    "nginx_proxy/data/logs/*"
    "yt-dl/video/*"
)

# LOGS
LOG_FILE="/var/log/docker_backup.log"

#############################
# COULEURS
#############################
NC="\e[0m"
GREEN="\e[32m"
YELLOW="\e[33m"
CYAN="\e[36m"
RED="\e[31m"

#############################
# FONCTIONS
#############################

log_message() {
    local msg="$1"
    local now
    now="$(date +'%Y-%m-%d %H:%M:%S')"
    echo "$now - $msg" >> "$LOG_FILE"
    echo -e "$now - $msg"
}

format_time() {
  local t=$1
  ((h=t/3600))
  ((m=(t%3600)/60))
  ((s=t%60))
  printf "%02d:%02d:%02d\n" $h $m $s
}

check_pigz() {
    if ! command -v pigz >/dev/null 2>&1; then
        echo -e "${YELLOW}pigz n'est pas installé. Voulez-vous l’installer ? (y/n)${NC}"
        read rep
        if [ "$rep" = "y" ]; then
            sudo apt update && sudo apt install -y pigz || {
                echo -e "${RED}Échec de l’installation de pigz. Abandon.${NC}"
                exit 1
            }
        else
            echo -e "${RED}pigz est requis pour ce script. Abandon.${NC}"
            exit 1
        fi
    fi
}

rotate_backups() {
    log_message "Nettoyage des anciens backups (conserver les $MAX_BACKUPS plus récents)..."

    # TAR
    mapfile -t backups_tar < <(ls -1t "$BACKUP_DIR"/docker_backup_*.tar.gz 2>/dev/null || true)
    if [ "${#backups_tar[@]}" -gt "$MAX_BACKUPS" ]; then
        for f in "${backups_tar[@]:$MAX_BACKUPS}"; do
            log_message "Suppression ancien backup tar : $f"
            rm -f "$f"
        done
    fi

    # Dossiers config_
    mapfile -t backups_cfg < <(ls -1td "$BACKUP_DIR"/config_* 2>/dev/null || true)
    if [ "${#backups_cfg[@]}" -gt "$MAX_BACKUPS" ]; then
        for d in "${backups_cfg[@]:$MAX_BACKUPS}"; do
            log_message "Suppression ancien dossier config : $d"
            rm -rf "$d"
        done
    fi
}

#############################
# DÉBUT SCRIPT
#############################

SECONDS=0

check_pigz

mkdir -p "$BACKUP_DIR" "$CONFIG_DIR"
touch "$LOG_FILE"

echo -e "${CYAN}=== Backup Docker + Configs (Portainer / CasaOS) ===${NC}"
log_message "Début sauvegarde Docker + configs Portainer & CasaOS..."

##############################################
# 1) Sauvegarde TAR via pigz + exclusions
##############################################
log_message "Création de l’archive : $BACKUP_FILE"

# Construction des arguments d'exclusion dynamiques
EXCLUDE_ARGS=(
    "--exclude=*.log"
    "--exclude=.composer"
    "--exclude=.aptitude"
    "--exclude=.cache"
    "--exclude=.cmake"
    "--exclude=.yarn"
    "--exclude=.w3m"
    "--exclude=.pip"
    "--exclude=.pm2"
    "--exclude=.pm"
    "--exclude=.bundle"
    "--exclude=.gem"
    "--exclude=.cpan"
    "--exclude=.cpanm"
    "--exclude=.git"
    "--exclude=.local"
    "--exclude=.npm"
    "--exclude=.nvm"
    "--exclude=.rvm"
    "--exclude=node_modules"
    "--exclude=lost+found"
    "--exclude=casaos_data"
)

for d in "${EXCLUDE_DIRS[@]}"; do
    EXCLUDE_ARGS+=( "--exclude=$d" )
done

tar -cf "$BACKUP_FILE" -I pigz \
 --directory="$SOURCE_DIR" \
 "${EXCLUDE_ARGS[@]}" \
 . 2>> "$LOG_FILE"

if [ $? -ne 0 ]; then
    log_message "ERREUR lors de la création du tar."
    echo -e "${RED}Erreur lors de la création de l’archive.${NC}"
    exit 1
fi

##############################################
# 2) Extraction des docker-compose
#    - CasaOS:   config_<date>/casaos/<container>/
#    - Docker:   config_<date>/docker/<container>/
##############################################

log_message "Extraction des docker-compose CasaOS..."
if [ -d "$SOURCE_DIR/casaos_data" ]; then
    find "$SOURCE_DIR/casaos_data" -maxdepth 3 -type f -name "docker-compose.y*ml" | while read file; do
        container_name=$(basename "$(dirname "$file")")
        dest_dir="$CONFIG_DIR/casaos/$container_name"
        mkdir -p "$dest_dir"
        cp "$file" "$dest_dir/"
        log_message "  [CasaOS] → Compose trouvé : $file"
    done
fi

log_message "Extraction des docker-compose Docker (hors casaos_data)..."
find "$SOURCE_DIR" -type f -name "docker-compose.y*ml" ! -path "$SOURCE_DIR/casaos_data/*" | while read file; do
    container_name=$(basename "$(dirname "$file")")
    dest_dir="$CONFIG_DIR/docker/$container_name"
    mkdir -p "$dest_dir"
    cp "$file" "$dest_dir/"
    log_message "  [Docker] → Compose trouvé : $file"
done

##############################################
# 3) Config Portainer (full)
##############################################
PORTAINER_CONFIG_DIR="$CONFIG_DIR/portainer/full_config"
PORTAINER_FILES=0

if docker volume inspect portainer_data >/dev/null 2>&1; then
    log_message "Sauvegarde config Portainer..."
    mkdir -p "$PORTAINER_CONFIG_DIR"
    cp -r /var/lib/docker/volumes/portainer_data/_data/* "$PORTAINER_CONFIG_DIR/" 2>>"$LOG_FILE"
    PORTAINER_FILES=$(find "$PORTAINER_CONFIG_DIR" -type f 2>/dev/null | wc -l)
else
    log_message "Portainer non détecté (volume portainer_data absent)."
fi

##############################################
# 4) Config CasaOS (full)
##############################################
CASAOS_CONFIG_DIR="$CONFIG_DIR/casaos/full_config"
CASAOS_FILES=0

if [ -d "/var/lib/casaos" ]; then
    log_message "Sauvegarde config CasaOS (full)..."
    mkdir -p "$CASAOS_CONFIG_DIR"
    cp -r /var/lib/casaos/* "$CASAOS_CONFIG_DIR/" 2>>"$LOG_FILE"
        CASAOS_FILES=$(find "$CONFIG_DIR/casaos" -type f -name "docker-compose.y*ml" ! -path "$CONFIG_DIR/casaos/full_config/*" 2>/dev/null | wc -l)
else
    log_message "CasaOS non détecté (/var/lib/casaos manquant)."
fi

##############################################
# 5) Comptages finaux (sur le backup courant)
##############################################

# Compose dans le backup (docker + casaos compose seulement)
CASAOS_COMPOSE_BACKUP=$(find "$CONFIG_DIR/casaos" -maxdepth 3 -type f -name "docker-compose.y*ml" ! -path "$CASAOS_CONFIG_DIR/*" 2>/dev/null | wc -l)
DOCKER_COMPOSE_BACKUP=$(find "$CONFIG_DIR/docker" -type f -name "docker-compose.y*ml" 2>/dev/null | wc -l)
TOTAL_COMPOSE_BACKUP=$((CASAOS_COMPOSE_BACKUP + DOCKER_COMPOSE_BACKUP))

# Compose dans le dossier source (hors casaos_data)
SOURCE_COMPOSE_COUNT=$(find "$SOURCE_DIR" -type f -name "docker-compose.y*ml" ! -path "$SOURCE_DIR/casaos_data/*" 2>/dev/null | wc -l)

# Rotation des anciens backups
rotate_backups

# Nombre total de tar.gz
TOTAL_TAR=$(ls -1 "$BACKUP_DIR"/docker_backup_*.tar.gz 2>/dev/null | wc -l)

# Oldest / newest après rotation
OLDEST_BACKUP=$(ls -1 "$BACKUP_DIR"/docker_backup_*.tar.gz 2>/dev/null | head -n1)
NEWEST_BACKUP=$(ls -1 "$BACKUP_DIR"/docker_backup_*.tar.gz 2>/dev/null | tail -n1)

DURATION="$(format_time $SECONDS)"

##############################################
# 6) RÉSUMÉS
##############################################

log_message "----- RÉSUMÉ DOCKER -----"
log_message "Compose source (hors CasaOS) : $SOURCE_COMPOSE_COUNT"
log_message "Compose backup (config/docker) : $DOCKER_COMPOSE_BACKUP"
log_message "Dossier compose Docker backup : $CONFIG_DIR/docker"

log_message "----- RÉSUMÉ CASAOS -----"
log_message "Compose CasaOS backup (config/casaos/<container>) : $CASAOS_COMPOSE_BACKUP"
log_message "Dossier CasaOS backup : $CONFIG_DIR/casaos"

log_message "----- RÉSUMÉ PORTAINER -----"
log_message "Fichiers config Portainer (full_config) : $PORTAINER_FILES"
log_message "Dossier Portainer backup : $PORTAINER_CONFIG_DIR"

log_message "----- RÉSUMÉ GLOBAL -----"
log_message "Nombre de .tar.gz : $TOTAL_TAR"
log_message "Backup le plus ancien : ${OLDEST_BACKUP:-N/A}"
log_message "Backup le plus récent : ${NEWEST_BACKUP:-N/A}"
log_message "Archive courante : $BACKUP_FILE"
log_message "Dossier config courant : $CONFIG_DIR"
log_message "Durée totale : $DURATION"

echo -e "${GREEN}===== BACKUP TERMINÉ =====${NC}"
echo -e "${CYAN}----- DOCKER -----${NC}"
echo -e "${CYAN}Compose source (hors CasaOS) : ${GREEN}$SOURCE_COMPOSE_COUNT${NC}"
echo -e "${CYAN}Compose backup (Docker)      : ${GREEN}$DOCKER_COMPOSE_BACKUP${NC}"
echo -e "${CYAN}Dossier compose Docker       : ${YELLOW}$CONFIG_DIR/docker${NC}"

echo -e "${CYAN}----- CASAOS -----${NC}"
echo -e "${CYAN}Compose CasaOS backup        : ${GREEN}$CASAOS_COMPOSE_BACKUP${NC}"
echo -e "${CYAN}Dossier CasaOS backup        : ${YELLOW}$CONFIG_DIR/casaos${NC}"

echo -e "${CYAN}----- PORTAINER -----${NC}"
echo -e "${CYAN}Fichiers config Portainer    : ${GREEN}$PORTAINER_FILES${NC}"
echo -e "${CYAN}Dossier Portainer backup     : ${YELLOW}$PORTAINER_CONFIG_DIR${NC}"

echo -e "${CYAN}----- GLOBAL -----${NC}"
echo -e "${CYAN}Nombre de .tar.gz            : ${GREEN}$TOTAL_TAR${NC}"
echo -e "${CYAN}Oldest backup                : ${YELLOW}${OLDEST_BACKUP:-N/A}${NC}"
echo -e "${CYAN}Newest backup                : ${YELLOW}${NEWEST_BACKUP:-N/A}${NC}"
echo -e "${CYAN}Archive courante             : ${YELLOW}$BACKUP_FILE${NC}"
echo -e "${CYAN}Dossier config courant       : ${YELLOW}$CONFIG_DIR${NC}"
echo -e "${CYAN}Durée totale                 : ${GREEN}$DURATION${NC}"
