#!/bin/bash

# Laravel Timebank Master Backup Script
# Orchestrates database and storage backups with health checks
# Usage: ./backup-all.sh [backup_type] [options]
# backup_type: daily (default), weekly, monthly
# options: --storage-only, --database-only, --verify, --notify

set -e  # Exit on any error

# Configuration
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="$(dirname "$SCRIPT_DIR")"
BACKUP_ROOT_DIR="$PROJECT_ROOT/backups"
LOG_FILE="$BACKUP_ROOT_DIR/backup.log"
HEALTH_CHECK_FILE="$BACKUP_ROOT_DIR/health_check.json"

# Create backup directories
mkdir -p "$BACKUP_ROOT_DIR/logs"

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

# Logging function with colors
log() {
    local level="$1"
    local message="$2"
    local timestamp="[$(date '+%Y-%m-%d %H:%M:%S')]"
    
    case "$level" in
        "INFO")
            echo -e "${timestamp} ${BLUE}[INFO]${NC} $message" | tee -a "$LOG_FILE"
            ;;
        "SUCCESS")
            echo -e "${timestamp} ${GREEN}[SUCCESS]${NC} $message" | tee -a "$LOG_FILE"
            ;;
        "WARNING")
            echo -e "${timestamp} ${YELLOW}[WARNING]${NC} $message" | tee -a "$LOG_FILE"
            ;;
        "ERROR")
            echo -e "${timestamp} ${RED}[ERROR]${NC} $message" | tee -a "$LOG_FILE"
            ;;
        *)
            echo -e "${timestamp} $level $message" | tee -a "$LOG_FILE"
            ;;
    esac
}

# Function to show usage
show_usage() {
    echo "Usage: $0 [backup_type] [options]"
    echo ""
    echo "Backup Types:"
    echo "  daily    - Daily backup (default)"
    echo "  weekly   - Weekly backup"
    echo "  monthly  - Monthly backup"
    echo ""
    echo "Options:"
    echo "  --storage-only   - Backup only storage files"
    echo "  --database-only  - Backup only database"
    echo "  --verify        - Verify backups after creation"
    echo "  --notify        - Send notification on completion"
    echo "  --help          - Show this help message"
    echo ""
    exit 0
}

# Health check function
health_check() {
    log "INFO" "Starting backup health check"
    
    local status="healthy"
    local issues=()
    
    # Check disk space (warn if less than 1GB free)
    local available_space=$(df "$BACKUP_ROOT_DIR" | awk 'NR==2 {print $4}')
    local available_mb=$((available_space / 1024))
    
    if [ "$available_mb" -lt 1024 ]; then
        status="warning"
        issues+=("Low disk space: ${available_mb}MB available")
    fi
    
    # Check if backup scripts exist and are executable
    for script in "backup-database.sh" "backup-storage.sh"; do
        if [ ! -x "$SCRIPT_DIR/$script" ]; then
            status="error"
            issues+=("Script not found or not executable: $script")
        fi
    done
    
    # Check environment file
    if [ ! -f "$PROJECT_ROOT/.env" ]; then
        status="error"
        issues+=("Environment file (.env) not found")
    fi
    
    # Generate health check report
    cat > "$HEALTH_CHECK_FILE" <<EOF
{
    "timestamp": "$(date -Iseconds)",
    "status": "$status",
    "available_space_mb": $available_mb,
    "issues": [$(printf '"%s",' "${issues[@]}" | sed 's/,$//')],
    "backup_directory": "$BACKUP_ROOT_DIR",
    "last_check": "$(date)"
}
EOF
    
    if [ "$status" = "error" ]; then
        log "ERROR" "Health check failed. Issues found:"
        for issue in "${issues[@]}"; do
            log "ERROR" "  - $issue"
        done
        return 1
    elif [ "$status" = "warning" ]; then
        log "WARNING" "Health check completed with warnings:"
        for issue in "${issues[@]}"; do
            log "WARNING" "  - $issue"
        done
    else
        log "SUCCESS" "Health check passed"
    fi
    
    return 0
}

# Backup verification function
verify_backups() {
    log "INFO" "Verifying recent backups"
    
    local verification_passed=true
    
    # Verify database backups
    local latest_db_backup=$(find "$BACKUP_ROOT_DIR/database" -name "*.sql.gz" -type f -mtime -1 | head -n 1)
    if [ -n "$latest_db_backup" ]; then
        if gzip -t "$latest_db_backup" 2>/dev/null; then
            log "SUCCESS" "Database backup verified: $(basename "$latest_db_backup")"
        else
            log "ERROR" "Database backup verification failed: $(basename "$latest_db_backup")"
            verification_passed=false
        fi
    else
        log "WARNING" "No recent database backup found"
    fi
    
    # Verify storage backups
    local latest_storage_backup=$(find "$BACKUP_ROOT_DIR/storage" -name "*.tar.gz" -type f -mtime -1 | head -n 1)
    if [ -n "$latest_storage_backup" ]; then
        if tar -tzf "$latest_storage_backup" >/dev/null 2>&1; then
            log "SUCCESS" "Storage backup verified: $(basename "$latest_storage_backup")"
        else
            log "ERROR" "Storage backup verification failed: $(basename "$latest_storage_backup")"
            verification_passed=false
        fi
    else
        log "WARNING" "No recent storage backup found"
    fi
    
    return $verification_passed
}

# Notification function
send_notification() {
    local subject="$1"
    local message="$2"
    local status="$3"
    
    # Try multiple notification methods
    
    # Method 1: Email (if mail is available and configured)
    if command -v mail >/dev/null 2>&1; then
        echo "$message" | mail -s "$subject" "${BACKUP_NOTIFY_EMAIL:-$USER@localhost}" 2>/dev/null || true
    fi
    
    # Method 2: System notification (if notify-send is available)
    if command -v notify-send >/dev/null 2>&1 && [ -n "$DISPLAY" ]; then
        notify-send "$subject" "$message" 2>/dev/null || true
    fi
    
    # Method 3: Webhook (if BACKUP_WEBHOOK_URL is set)
    if [ -n "$BACKUP_WEBHOOK_URL" ] && command -v curl >/dev/null 2>&1; then
        curl -X POST "$BACKUP_WEBHOOK_URL" \
             -H "Content-Type: application/json" \
             -d "{\"subject\":\"$subject\",\"message\":\"$message\",\"status\":\"$status\"}" \
             2>/dev/null || true
    fi
    
    # Method 4: Log file notification marker
    log "INFO" "NOTIFICATION: $subject - $message"
}

# Parse command line arguments
BACKUP_TYPE="daily"
STORAGE_ONLY=false
DATABASE_ONLY=false
VERIFY=false
NOTIFY=false

while [[ $# -gt 0 ]]; do
    case $1 in
        daily|weekly|monthly)
            BACKUP_TYPE="$1"
            shift
            ;;
        --storage-only)
            STORAGE_ONLY=true
            shift
            ;;
        --database-only)
            DATABASE_ONLY=true
            shift
            ;;
        --verify)
            VERIFY=true
            shift
            ;;
        --notify)
            NOTIFY=true
            shift
            ;;
        --help)
            show_usage
            ;;
        *)
            log "ERROR" "Unknown option: $1"
            show_usage
            ;;
    esac
done

# Main execution
main() {
    log "INFO" "============================================"
    log "INFO" "Starting Timebank $BACKUP_TYPE backup process"
    log "INFO" "Time: $(date)"
    log "INFO" "============================================"
    
    local start_time=$(date +%s)
    local backup_success=true
    local status_message=""
    
    # Pre-backup health check
    if ! health_check; then
        log "ERROR" "Health check failed, aborting backup"
        exit 1
    fi
    
    # Database backup
    if [ "$STORAGE_ONLY" = false ]; then
        log "INFO" "Starting database backup..."
        if "$SCRIPT_DIR/backup-database.sh" "$BACKUP_TYPE"; then
            log "SUCCESS" "Database backup completed"
        else
            log "ERROR" "Database backup failed"
            backup_success=false
        fi
    fi
    
    # Storage backup
    if [ "$DATABASE_ONLY" = false ]; then
        log "INFO" "Starting storage backup..."
        if "$SCRIPT_DIR/backup-storage.sh" "$BACKUP_TYPE"; then
            log "SUCCESS" "Storage backup completed"
        else
            log "ERROR" "Storage backup failed"
            backup_success=false
        fi
    fi
    
    # Backup verification
    if [ "$VERIFY" = true ]; then
        if verify_backups; then
            log "SUCCESS" "Backup verification passed"
        else
            log "WARNING" "Backup verification had issues"
        fi
    fi
    
    # Calculate execution time
    local end_time=$(date +%s)
    local execution_time=$((end_time - start_time))
    local execution_time_formatted=$(date -d@$execution_time -u +%H:%M:%S)
    
    # Generate final status
    if [ "$backup_success" = true ]; then
        status_message="Backup completed successfully in $execution_time_formatted"
        log "SUCCESS" "$status_message"
        
        # Generate backup summary
        log "INFO" "Backup Summary:"
        log "INFO" "  - Type: $BACKUP_TYPE"
        log "INFO" "  - Duration: $execution_time_formatted"
        log "INFO" "  - Location: $BACKUP_ROOT_DIR"
        
        if [ "$NOTIFY" = true ]; then
            send_notification "Timebank Backup Success" "$status_message" "success"
        fi
        
    else
        status_message="Backup completed with errors in $execution_time_formatted"
        log "ERROR" "$status_message"
        
        if [ "$NOTIFY" = true ]; then
            send_notification "Timebank Backup Failed" "$status_message" "error"
        fi
        
        exit 1
    fi
    
    log "INFO" "============================================"
    log "INFO" "Backup process finished"
    log "INFO" "============================================"
}

# Trap to handle interrupts
trap 'log "ERROR" "Backup interrupted by user"; exit 1' INT TERM

# Run main function
main "$@"