#!/bin/bash

# Script to backup all OrangePi services to NAS
# This creates a complete backup of service data and Docker volumes

set -euo pipefail

# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color

# Configuration
BACKUP_DATE=$(date +%Y%m%d-%H%M%S)
BACKUP_ROOT="/mnt/synology/homes/jannick/backups/orangepi-manual-$BACKUP_DATE"
LOG_FILE="$BACKUP_ROOT/backup.log"

# Function to log messages
log() {
    local level=$1
    shift
    local message="$@"
    local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
    
    case $level in
        "INFO")
            echo -e "${BLUE}[INFO]${NC} $message"
            ;;
        "SUCCESS")
            echo -e "${GREEN}[SUCCESS]${NC} $message"
            ;;
        "WARNING")
            echo -e "${YELLOW}[WARNING]${NC} $message"
            ;;
        "ERROR")
            echo -e "${RED}[ERROR]${NC} $message"
            ;;
    esac
    
    # Only log to file if log file exists
    if [[ -f "$LOG_FILE" ]]; then
        echo "[$timestamp] [$level] $message" >> "$LOG_FILE" 2>/dev/null || true
    fi
}

# Function to backup a directory
backup_directory() {
    local source=$1
    local target=$2
    local description=$3
    
    if [[ -d "$source" ]]; then
        log "INFO" "Backing up $description..."
        mkdir -p "$(dirname "$target")"
        if sudo cp -av "$source" "$target" >> "$LOG_FILE" 2>&1; then
            log "SUCCESS" "  ✓ $description backed up"
            return 0
        else
            log "WARNING" "  ⚠ Some errors during $description backup (check log)"
            return 1
        fi
    else
        log "WARNING" "  ⚠ $description not found at $source"
        return 1
    fi
}

# Function to backup a Docker volume
backup_docker_volume() {
    local volume_name=$1
    local target_dir=$2
    local description=$3
    
    log "INFO" "Backing up $description (Docker volume)..."
    
    # Check if volume exists
    if docker volume inspect "$volume_name" &>/dev/null; then
        mkdir -p "$target_dir"
        if docker run --rm -v "$volume_name":/data -v "$target_dir":/backup alpine \
            tar czf "/backup/${volume_name}.tar.gz" -C /data . >> "$LOG_FILE" 2>&1; then
            log "SUCCESS" "  ✓ $description backed up"
            return 0
        else
            log "ERROR" "  ✗ Failed to backup $description"
            return 1
        fi
    else
        log "WARNING" "  ⚠ Docker volume $volume_name not found"
        return 1
    fi
}

# Main execution
main() {
    log "INFO" "==================== BACKUP STARTED ===================="
    log "INFO" "Backup destination: $BACKUP_ROOT"
    
    # Create backup root directory
    if ! mkdir -p "$BACKUP_ROOT"; then
        echo "ERROR: Failed to create backup directory. Is NAS mounted?" >&2
        exit 1
    fi
    
    # Initialize log file
    touch "$LOG_FILE" || {
        echo "ERROR: Failed to create log file at $LOG_FILE" >&2
        exit 1
    }
    log "INFO" "Log file: $LOG_FILE"
    
    # Track statistics
    local total_operations=0
    local successful_operations=0
    
    # ============ CRITICAL SERVICES ============
    log "INFO" ""
    log "INFO" "======== CRITICAL SERVICES ========"
    
    # Vaultwarden (Passwords)
    ((total_operations++))
    backup_directory "/home/orangepi/vaultwarden/data" \
                    "$BACKUP_ROOT/vaultwarden/data" \
                    "Vaultwarden (passwords)" && ((successful_operations++)) || true
    
    # Immich (Photos)
    ((total_operations++))
    backup_directory "/home/orangepi/immich-app" \
                    "$BACKUP_ROOT/immich/immich-app" \
                    "Immich app data" && ((successful_operations++)) || true
    
    ((total_operations++))
    backup_docker_volume "immich_model-cache" \
                        "$BACKUP_ROOT/immich" \
                        "Immich ML models" && ((successful_operations++)) || true
    
    # Home Assistant (Automations)
    ((total_operations++))
    backup_docker_volume "homeassistant_homeassistant_config" \
                        "$BACKUP_ROOT/homeassistant" \
                        "Home Assistant config" && ((successful_operations++)) || true
    
    # ============ IMPORTANT SERVICES ============
    log "INFO" ""
    log "INFO" "======== IMPORTANT SERVICES ========"
    
    # Paperless-NGX (Documents)
    ((total_operations++))
    backup_docker_volume "paperless_pgdata" \
                        "$BACKUP_ROOT/paperless" \
                        "Paperless PostgreSQL database" && ((successful_operations++)) || true
    
    ((total_operations++))
    backup_docker_volume "paperless_data" \
                        "$BACKUP_ROOT/paperless" \
                        "Paperless application data" && ((successful_operations++)) || true
    
    # Syncthing (File Sync)
    ((total_operations++))
    backup_directory "/home/orangepi/syncthing/config" \
                    "$BACKUP_ROOT/syncthing/config" \
                    "Syncthing config" && ((successful_operations++)) || true
    
    # Duplicati (Backup Configs)
    ((total_operations++))
    backup_directory "/home/orangepi/duplicati/config" \
                    "$BACKUP_ROOT/duplicati/config" \
                    "Duplicati config" && ((successful_operations++)) || true
    
    # ============ MEDIA SERVICES ============
    log "INFO" ""
    log "INFO" "======== MEDIA SERVICES ========"
    
    # Jellyfin
    ((total_operations++))
    backup_directory "/home/orangepi/jellyfin/config" \
                    "$BACKUP_ROOT/jellyfin/config" \
                    "Jellyfin config" && ((successful_operations++)) || true
    
    # Media services (Radarr/Sonarr/Bazarr)
    for service in radarr sonarr bazarr; do
        ((total_operations++))
        backup_directory "/home/orangepi/$service" \
                        "$BACKUP_ROOT/media-services/$service" \
                        "$service" && ((successful_operations++)) || true
    done
    
    # ============ INFRASTRUCTURE SERVICES ============
    log "INFO" ""
    log "INFO" "======== INFRASTRUCTURE SERVICES ========"
    
    # Traefik (Reverse Proxy)
    ((total_operations++))
    backup_directory "/home/orangepi/traefik" \
                    "$BACKUP_ROOT/traefik" \
                    "Traefik" && ((successful_operations++)) || true
    
    # Pi-hole (DNS)
    ((total_operations++))
    backup_directory "/home/orangepi/pihole" \
                    "$BACKUP_ROOT/pihole" \
                    "Pi-hole" && ((successful_operations++)) || true
    
    # OpenCloud/Nextcloud volumes
    ((total_operations++))
    backup_docker_volume "opencloud_opencloud-apps" \
                        "$BACKUP_ROOT/opencloud" \
                        "OpenCloud apps" && ((successful_operations++)) || true
    
    ((total_operations++))
    backup_docker_volume "opencloud_radicale-data" \
                        "$BACKUP_ROOT/opencloud" \
                        "Radicale calendar data" && ((successful_operations++)) || true
    
    # ============ CONFIGURATION FILES ============
    log "INFO" ""
    log "INFO" "======== CONFIGURATION FILES ========"
    
    # Docker Compose files
    ((total_operations++))
    log "INFO" "Collecting Docker Compose files..."
    mkdir -p "$BACKUP_ROOT/docker-compose"
    find /home/orangepi -maxdepth 3 \( -name "docker-compose*.yml" -o -name "compose*.yml" \) \
        -not -path "*/dotfiles/*" -exec cp -av {} "$BACKUP_ROOT/docker-compose/" \; >> "$LOG_FILE" 2>&1
    if [[ $? -eq 0 ]]; then
        log "SUCCESS" "  ✓ Docker Compose files collected"
        ((successful_operations++))
    fi
    
    # Scripts
    ((total_operations++))
    log "INFO" "Backing up scripts..."
    mkdir -p "$BACKUP_ROOT/scripts"
    for script in /home/orangepi/*.sh; do
        if [[ -f "$script" ]]; then
            cp -av "$script" "$BACKUP_ROOT/scripts/" >> "$LOG_FILE" 2>&1
        fi
    done
    log "SUCCESS" "  ✓ Scripts backed up"
    ((successful_operations++))
    
    # Restic backup config
    ((total_operations++))
    backup_directory "/home/orangepi/.restic-password" \
                    "$BACKUP_ROOT/backup-configs/.restic-password" \
                    "Restic password file" && ((successful_operations++)) || true
    
    # Crontab
    ((total_operations++))
    log "INFO" "Backing up crontab..."
    if crontab -l > "$BACKUP_ROOT/crontab-backup.txt" 2>/dev/null; then
        log "SUCCESS" "  ✓ Crontab backed up"
        ((successful_operations++))
    else
        log "WARNING" "  ⚠ No crontab found"
    fi
    
    # ============ CREATE SUMMARY ============
    log "INFO" ""
    log "INFO" "Creating backup summary..."
    
    cat > "$BACKUP_ROOT/backup-summary.txt" << EOF
OrangePi Services Backup Summary
================================

Backup Date: $(date)
Backup Location: $BACKUP_ROOT

Services Backed Up:
------------------
$(cd "$BACKUP_ROOT" && find . -maxdepth 1 -type d -not -name "." | sort | sed 's/^\.\//- /')

Docker Volumes Backed Up:
------------------------
$(cd "$BACKUP_ROOT" && find . -name "*.tar.gz" | sort | sed 's/^\.\//- /')

Statistics:
-----------
Total backup operations: $total_operations
Successful operations: $successful_operations
Success rate: $(( successful_operations * 100 / total_operations ))%

Backup Size:
-----------
$(du -sh "$BACKUP_ROOT" 2>/dev/null | cut -f1)

To Restore:
-----------
1. For directories: cp -av <backup_path> <destination>
2. For Docker volumes: 
   docker volume create <volume_name>
   docker run --rm -v <volume_name>:/data -v <backup_dir>:/backup alpine tar xzf /backup/<volume>.tar.gz -C /data

Notes:
------
- Media files are stored on Synology NAS and not included in this backup
- Some permission errors are normal for files owned by Docker containers
- Check backup.log for detailed information
EOF
    
    # Display summary
    log "INFO" ""
    log "INFO" "==================== BACKUP COMPLETED ===================="
    log "SUCCESS" "Backup location: $BACKUP_ROOT"
    log "SUCCESS" "Total operations: $total_operations"
    log "SUCCESS" "Successful: $successful_operations ($(( successful_operations * 100 / total_operations ))%)"
    log "INFO" "Backup size: $(du -sh "$BACKUP_ROOT" 2>/dev/null | cut -f1)"
    log "INFO" ""
    log "INFO" "Summary file: $BACKUP_ROOT/backup-summary.txt"
    log "INFO" "Full log: $LOG_FILE"
}

# Run main function
main "$@"