#!/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 (dossiers datés)
MAX_BACKUPS=3

# Date interne (pour logs / JSON)
DATE_RAW="$(date +'%Y%m%d_%H%M%S')"
# Date pour le dossier de backup (format humain demandé)
DATE_DIR="$(date +'%Y.%m.%d_%H-%M-%S')"

# Dossier de ce backup
RUN_DIR="$BACKUP_DIR/$DATE_DIR"

# Fichiers TAR dans le dossier de ce backup
BACKUP_FILE="$RUN_DIR/docker_backup.tar.gz"
CASAOS_FULL_TAR="$RUN_DIR/casaos_full_backup.tar.gz"

# Dossier où l'on met les compose / configs
CONFIG_DIR="$RUN_DIR"

# Dossiers à exclure (chemins relatifs à $SOURCE_DIR pour le tar Docker)
EXCLUDE_DIRS=(
    "docker_var_lib"
    "1_Backups"
    "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 "Rotation des anciens backups (conserver les $MAX_BACKUPS plus récents)..."

    # On ne garde que les dossiers datés dans BACKUP_DIR
    mapfile -t backups_dirs < <(ls -1td "$BACKUP_DIR"/*/ 2>/dev/null || true)

    if [ "${#backups_dirs[@]}" -gt "$MAX_BACKUPS" ]; then
        for d in "${backups_dirs[@]:$MAX_BACKUPS}"; do
            log_message "Suppression ancien backup (dossier) : $d"
            rm -rf "$d"
        done
    fi
}

get_size() {
    du -sh "$1" 2>/dev/null | awk '{print $1}'
}

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

SECONDS=0

check_pigz

mkdir -p "$RUN_DIR"
touch "$LOG_FILE"

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

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

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"
)

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 Docker."
    echo -e "${RED}Erreur lors de la création de l’archive Docker.${NC}"
    exit 1
fi

##############################################
# 2) Extraction des docker-compose
#    - CasaOS:   RUN_DIR/casaos/<container>/
#    - Docker:   RUN_DIR/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 & dossiers exclus)..."
find "$SOURCE_DIR" -mindepth 2 -maxdepth 2 -type f -name "docker-compose.y*ml" \
    ! -path "$SOURCE_DIR/casaos_data/*" \
    ! -path "$SOURCE_DIR/docker_var_lib/*" \
    2>/dev/null | while read file; do
        container_name=$(basename "$(dirname "$file")")
        dest_dir="$CONFIG_DIR/Compose/$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"
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
    PORTAINER_CONFIG_DIR=""
fi

##############################################
# 4) Config CasaOS (full + tar.gz)
##############################################
CASAOS_CONFIG_DIR="$CONFIG_DIR/casaos/full_config"

if [ -d "/var/lib/casaos" ]; then
    log_message "Sauvegarde config CasaOS (full vers $CASAOS_CONFIG_DIR)..."
    mkdir -p "$CASAOS_CONFIG_DIR"
    cp -r /var/lib/casaos/* "$CASAOS_CONFIG_DIR/" 2>>"$LOG_FILE"
fi

# Création du second tar.gz CasaOS FULL (config + volumes casaos_data)
if [ -d "/var/lib/casaos" ] || [ -d "$SOURCE_DIR/casaos_data" ]; then
    CASAOS_TAR_SOURCES=()
    [ -d "/var/lib/casaos" ] && CASAOS_TAR_SOURCES+=( "/var/lib/casaos" )
    [ -d "$SOURCE_DIR/casaos_data" ] && CASAOS_TAR_SOURCES+=( "$SOURCE_DIR/casaos_data" )

    if [ "${#CASAOS_TAR_SOURCES[@]}" -gt 0 ]; then
        log_message "Création de l’archive CASAOS FULL : $CASAOS_FULL_TAR"
        tar -cf "$CASAOS_FULL_TAR" -I pigz "${CASAOS_TAR_SOURCES[@]}" 2>>"$LOG_FILE"
        if [ $? -ne 0 ]; then
            log_message "ERREUR lors de la création du tar CasaOS."
            echo -e "${RED}Erreur lors de la création de l’archive CasaOS.${NC}"
        fi
    fi
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)

# Compose dans le dossier source (uniquement /home/docker/<container>/docker-compose.*)
SOURCE_COMPOSE_COUNT=$(find "$SOURCE_DIR" -mindepth 2 -maxdepth 2 -type f -name "docker-compose.y*ml" \
    ! -path "$SOURCE_DIR/casaos_data/*" \
    ! -path "$SOURCE_DIR/docker_var_lib/*" \
    2>/dev/null | wc -l)

# Containers Docker "valides"
CONTAINERS_DOCKER=$(find "$SOURCE_DIR" -mindepth 1 -maxdepth 1 -type d \
    ! -path "$SOURCE_DIR/casaos_data" \
    ! -path "$SOURCE_DIR/docker_var_lib" \
    ! -path "$SOURCE_DIR/portainer" 2>/dev/null | wc -l)

# Rotation des anciens backups (par dossiers)
rotate_backups

# Nombre total de sets de backup (dossiers datés)
TOTAL_BACKUP_SETS=$(ls -1d "$BACKUP_DIR"/*/ 2>/dev/null | wc -l)

# Oldest / newest backup set
mapfile -t CURRENT_SETS < <(ls -1d "$BACKUP_DIR"/*/ 2>/dev/null | sort)
OLDEST_DIR="${CURRENT_SETS[0]}"
NEWEST_DIR="${CURRENT_SETS[${#CURRENT_SETS[@]}-1]}"

DURATION="$(format_time $SECONDS)"

# Tailles des backups courants
TAR_SIZE=$(get_size "$BACKUP_FILE")
CONFIG_SIZE=$(get_size "$CONFIG_DIR")
DOCKER_CONFIG_SIZE=$(get_size "$CONFIG_DIR/docker")

# CasaOS full config size (copie dans RUN_DIR/casaos/full_config)
if [ -d "$CASAOS_CONFIG_DIR" ]; then
    CASAOS_CONFIG_SIZE=$(get_size "$CASAOS_CONFIG_DIR")
else
    CASAOS_CONFIG_SIZE=""
fi

# CasaOS FULL TAR size
if [ -f "$CASAOS_FULL_TAR" ]; then
    CASAOS_FULL_TAR_SIZE=$(get_size "$CASAOS_FULL_TAR")
else
    CASAOS_FULL_TAR_SIZE=""
fi

# Portainer full config size
if [ -n "$PORTAINER_CONFIG_DIR" ] && [ -d "$PORTAINER_CONFIG_DIR" ]; then
    PORTAINER_CONFIG_SIZE=$(get_size "$PORTAINER_CONFIG_DIR")
else
    PORTAINER_CONFIG_SIZE=""
fi

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

echo -e "${GREEN}===== BACKUP TERMINÉ =====${NC}"
echo -e "${CYAN}Dossier backup courant       : ${YELLOW}$RUN_DIR${NC}"

##############################################
# LISTE DES DOSSIERS DOCKER PAR TAILLE (ASCII)
##############################################

echo -e "\n${CYAN}----- LISTE/TAILLE DES RÉPERTOIRES DOCKER -----${NC}"

DOCKER_DIRS=$(find "$SOURCE_DIR" -mindepth 1 -maxdepth 1 -type d \
    ! -path "$SOURCE_DIR/casaos_data" \
    ! -path "$SOURCE_DIR/docker_var_lib" \
    ! -path "$SOURCE_DIR/portainer" 2>/dev/null)

if [ -z "$DOCKER_DIRS" ]; then
    echo -e "${YELLOW}(Aucun dossier Docker trouvé)${NC}"
else
    echo -e "┌──────────────────────────┬─────────┬────────────────────────────────────────┐"
    printf "│ %-24s │ %-7s │ %-38s │\n" "Container" "Taille" "Chemin"
    echo -e "├──────────────────────────┼─────────┼────────────────────────────────────────┤"
    du -sh $DOCKER_DIRS 2>/dev/null | sort -hr | while read -r size path; do
        name=$(basename "$path")
        printf "│ %-24s │ %-7s │ %-38s │\n" "$name" "$size" "$path"
    done
    echo -e "└──────────────────────────┴─────────┴────────────────────────────────────────┘"
fi

#################################
# DOCKER
#################################
echo -e "${CYAN}\n----- DOCKER -----${NC}"
echo -e "${CYAN}Containers Docker détectés   : ${GREEN}$CONTAINERS_DOCKER${NC}"
echo -e "${CYAN}Compose source (Docker)      : ${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}Taille compose Docker        : ${GREEN}$DOCKER_CONFIG_SIZE${NC}"

#################################
# CASAOS (si présent)
#################################
if [ -d "$CONFIG_DIR/casaos" ] || [ -f "$CASAOS_FULL_TAR" ]; then
    echo -e "${CYAN}\n----- CASAOS -----${NC}"
    echo -e "${CYAN}Compose CasaOS backup        : ${GREEN}$CASAOS_COMPOSE_BACKUP${NC}"
    echo -e "${CYAN}Dossier CasaOS backup        : ${YELLOW}$CONFIG_DIR/casaos${NC}"
    [ -n "$CASAOS_CONFIG_SIZE" ] && echo -e "${CYAN}Taille config CasaOS (full)  : ${GREEN}$CASAOS_CONFIG_SIZE${NC}"
    if [ -f "$CASAOS_FULL_TAR" ]; then
        echo -e "${CYAN}Tar CasaOS FULL              : ${YELLOW}$CASAOS_FULL_TAR${NC}"
        echo -e "${CYAN}Taille tar CasaOS FULL       : ${GREEN}$CASAOS_FULL_TAR_SIZE${NC}"
    fi
fi

#################################
# PORTAINER (si présent)
#################################
if [ -n "$PORTAINER_CONFIG_DIR" ] && [ -d "$PORTAINER_CONFIG_DIR" ]; then
    echo -e "${CYAN}\n----- PORTAINER -----${NC}"
    echo -e "${CYAN}Fichiers config Portainer    : ${GREEN}$PORTAINER_FILES${NC}"
    echo -e "${CYAN}Dossier Portainer backup     : ${YELLOW}$PORTAINER_CONFIG_DIR${NC}"
    [ -n "$PORTAINER_CONFIG_SIZE" ] && echo -e "${CYAN}Taille Portainer (full)      : ${GREEN}$PORTAINER_CONFIG_SIZE${NC}"
fi

#################################
# GLOBAL
#################################
echo -e "${CYAN}\n----- GLOBAL -----${NC}"
echo -e "${CYAN}Nombre de sets de backup     : ${GREEN}$TOTAL_BACKUP_SETS${NC}"
echo -e "${CYAN}Oldest backup dir            : ${YELLOW}${OLDEST_DIR:-N/A}${NC}"
echo -e "${CYAN}Newest backup dir            : ${YELLOW}${NEWEST_DIR:-N/A}${NC}"
echo -e "${CYAN}Taille archive Docker tar.gz : ${GREEN}$TAR_SIZE${NC}"
[ -f "$CASAOS_FULL_TAR" ] && echo -e "${CYAN}Taille archive CasaOS tar.gz : ${GREEN}$CASAOS_FULL_TAR_SIZE${NC}"
echo -e "${CYAN}Taille dossier backup courant: ${GREEN}$CONFIG_SIZE${NC}"
echo -e "${CYAN}Archive Docker courante      : ${YELLOW}$BACKUP_FILE${NC}"
[ -f "$CASAOS_FULL_TAR" ] && echo -e "${CYAN}Archive CasaOS courante      : ${YELLOW}$CASAOS_FULL_TAR${NC}"
echo -e "${CYAN}Durée totale                 : ${GREEN}$DURATION${NC}"

#################################
# JSON (optionnel : ./script.sh --json)
#################################
if [ "$1" = "--json" ]; then
    echo ""
    echo "{"
    echo "  \"date_raw\": \"$DATE_RAW\","
    echo "  \"date_dir\": \"$DATE_DIR\","
    echo "  \"run_dir\": \"$RUN_DIR\","
    echo "  \"docker_backup_file\": \"$BACKUP_FILE\","
    echo "  \"docker_backup_size\": \"$TAR_SIZE\","
    echo "  \"casaos_full_backup_file\": \"${CASAOS_FULL_TAR:-}\","
    echo "  \"casaos_full_backup_size\": \"${CASAOS_FULL_TAR_SIZE:-}\","
    echo "  \"docker\": {"
    echo "    \"containers\": $CONTAINERS_DOCKER,"
    echo "    \"compose_source\": $SOURCE_COMPOSE_COUNT,"
    echo "    \"compose_backup\": $DOCKER_COMPOSE_BACKUP"
    echo "  },"
    echo "  \"casaos\": {"
    echo "    \"compose_backup\": $CASAOS_COMPOSE_BACKUP"
    echo "  },"
    echo "  \"portainer\": {"
    echo "    \"files\": $PORTAINER_FILES"
    echo "  },"
    echo "  \"backup_sets\": $TOTAL_BACKUP_SETS,"
    echo "  \"oldest_backup_dir\": \"${OLDEST_DIR:-}\","
    echo "  \"newest_backup_dir\": \"${NEWEST_DIR:-}\","
    echo "  \"duration\": \"$DURATION\""
    echo "}"
fi
