#!/bin/bash

# Define timestamp for logs and backup filenames
TIMESTAMP=$(date +"%Y%m%d_%H%M_%3N")
LOGFILE="DVDBR_${TIMESTAMP}.log"

# Function to log messages
log() {
    echo "[$(date +"%Y-%m-%d %H:%M:%S.%3N")] $1" | tee -a "$LOGFILE"
}

# Check if the user is in the docker group or requires sudo
if ! groups | grep -q '\bdocker\b'; then
    log "User is not in the docker group, requesting sudo access."
    sudo -v || { log "Failed to obtain sudo access."; exit 1; }
    SUDO_CMD="sudo"
else
    SUDO_CMD=""
fi

# List available Docker volumes
VOLUMES=$($SUDO_CMD docker volume ls --format "{{.Name}}")
if [[ -z "$VOLUMES" ]]; then
    log "No Docker volumes found. Exiting."
    exit 1
fi

# Ask which volumes to backup
log "Available Docker volumes:"
echo "$VOLUMES"
read -p "Enter the volume(s) to backup (space-separated): " SELECTED_VOLUMES

# Ask if timestamp should be included in the backup file name
read -p "Include timestamp in backup filename? [y/N]: " INCLUDE_TIMESTAMP

# Find running containers using selected volumes
declare -A CONTAINER_MAP
for VOLUME in $SELECTED_VOLUMES; do
    while read -r CONTAINER_ID; do
        if [[ -n "$CONTAINER_ID" ]]; then
            CONTAINER_NAME=$($SUDO_CMD docker ps --filter "id=$CONTAINER_ID" --format "{{.Names}}")
            CONTAINER_MAP["$CONTAINER_ID"]="$CONTAINER_NAME ($CONTAINER_ID)"
        fi
    done < <($SUDO_CMD docker ps --format "{{.ID}}" --filter "volume=$VOLUME")
done

# Display affected containers
if [[ "${#CONTAINER_MAP[@]}" -gt 0 ]]; then
    log "The following containers use the selected volumes and may be impacted: ${CONTAINER_MAP[*]}"
fi

# Ask if containers should be stopped before backup
read -p "Do you want to stop them before backup? (recommended) [y/N]: " STOP_CONTAINERS

# Ask for backup method
read -p "Save locally? [y/N]: " SAVE_LOCAL
read -p "Save to remote server via SSH? [y/N]: " SAVE_REMOTE

# Ask for local backup path if needed
if [[ "$SAVE_LOCAL" =~ ^[Yy]$ ]]; then
    read -p "Enter local backup directory (default: current directory): " LOCAL_PATH
    LOCAL_PATH=${LOCAL_PATH:-$(pwd)}
    mkdir -p "$LOCAL_PATH"
fi

# Ask for SSH details if remote backup is selected
if [[ "$SAVE_REMOTE" =~ ^[Yy]$ ]]; then
    read -p "Enter SSH private key path (default: ~/.ssh/id_rsa): " SSH_KEY
    SSH_KEY=${SSH_KEY:-~/.ssh/id_rsa}
    read -p "Enter SSH user: " SSH_USER
    read -p "Enter SSH server hostname/IP: " SSH_HOST
    read -p "Enter remote backup directory (default: ~/BACKUP): " REMOTE_PATH
    REMOTE_PATH=${REMOTE_PATH:-~/BACKUP}
fi

# Ask if containers should be restarted after backup (only if they were stopped)
if [[ "$STOP_CONTAINERS" =~ ^[Yy]$ ]]; then
    read -p "Restart stopped containers after backup? [y/N]: " RESTART_CONTAINERS
fi

# Summary before execution
echo -e "\nSummary of actions:"
echo "- Selected volumes: $SELECTED_VOLUMES"
echo "- Containers that may be using these volumes: ${CONTAINER_MAP[*]}"
echo "- Stop containers before backup: ${STOP_CONTAINERS}";
echo "- Restart stopped containers after backup: ${RESTART_CONTAINERS}";
echo "- Save locally: ${SAVE_LOCAL}"; [[ "$SAVE_LOCAL" =~ ^[Yy]$ ]] && echo "  -> Path: $LOCAL_PATH"
echo "- Save remotely: ${SAVE_REMOTE}"; [[ "$SAVE_REMOTE" =~ ^[Yy]$ ]] && echo "  -> SSH: $SSH_USER@$SSH_HOST:$REMOTE_PATH"
read -p "Proceed with backup? [y/N]: " CONFIRM
[[ "$CONFIRM" =~ ^[Yy]$ ]] || { log "Backup cancelled."; exit 0; }

# Stop containers if confirmed
if [[ "$STOP_CONTAINERS" =~ ^[Yy]$ ]]; then
    for CONTAINER_ID in "${!CONTAINER_MAP[@]}"; do
        log "Stopping container: ${CONTAINER_MAP[$CONTAINER_ID]}"
        $SUDO_CMD docker stop "$CONTAINER_ID"
    done
fi

# Perform backup
for VOLUME in $SELECTED_VOLUMES; do
    BACKUP_FILE="$VOLUME.tar.gz"
    [[ "$INCLUDE_TIMESTAMP" =~ ^[Yy]$ ]] && BACKUP_FILE="${VOLUME}_${TIMESTAMP}.tar.gz"

    if [[ "$SAVE_LOCAL" =~ ^[Yy]$ ]]; then
        log "Saving $VOLUME locally to $LOCAL_PATH/$BACKUP_FILE"
        $SUDO_CMD docker run --rm -v $VOLUME:/data:ro -v "$LOCAL_PATH:/backup" alpine tar czf "/backup/$BACKUP_FILE" -C /data .
    fi
    
    if [[ "$SAVE_REMOTE" =~ ^[Yy]$ ]]; then
        log "Streaming $VOLUME backup directly to remote server via ssh cat"
        if ! $SUDO_CMD docker run --rm -v $VOLUME:/data:ro alpine sh -c "tar czf - -C /data ." | ssh -i "$SSH_KEY" "$SSH_USER@$SSH_HOST" "cat > $REMOTE_PATH/$BACKUP_FILE"; then
            log "⚠️ ssh cat failed, trying rsync..."
            if ! rsync -avz -e "ssh -i $SSH_KEY" "$LOCAL_PATH/$BACKUP_FILE" "$SSH_USER@$SSH_HOST:$REMOTE_PATH/"; then
                log "⚠️ rsync failed, trying SCP..."
                scp -i "$SSH_KEY" "$LOCAL_PATH/$BACKUP_FILE" "$SSH_USER@$SSH_HOST:$REMOTE_PATH/"
            fi
        fi
    fi

done

# Restart stopped containers if requested
if [[ "$STOP_CONTAINERS" =~ ^[Yy]$ && "$RESTART_CONTAINERS" =~ ^[Yy]$ ]]; then
    for CONTAINER_ID in "${!CONTAINER_MAP[@]}"; do
        log "Restarting container: ${CONTAINER_MAP[$CONTAINER_ID]}"
        $SUDO_CMD docker start "$CONTAINER_ID"
    done
fi

log "Backup process completed successfully."