#!/usr/bin/env bash
# Retry functions with exponential backoff
# Usage: source "$SCRIPT_DIR/lib/common/retry.sh"

# Source logging if not already sourced
[ -z "$(type -t log_info)" ] && source "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/logging.sh"

# Retry a command with exponential backoff
# Usage: retry_command <max_attempts> <delay> <command> [args...]
retry_command() {
    local max_attempts="$1"
    local base_delay="$2"
    shift 2
    local command=("$@")
    
    local attempt=1
    local delay="$base_delay"
    
    while [ $attempt -le $max_attempts ]; do
        log_info "Attempt $attempt/$max_attempts: ${command[*]}"
        
        if "${command[@]}"; then
            return 0
        fi
        
        if [ $attempt -lt $max_attempts ]; then
            log_warn "Command failed, retrying in ${delay}s..."
            sleep "$delay"
            delay=$((delay * 2))  # Exponential backoff
        fi
        
        ((attempt++)) || true
    done
    
    log_error "Command failed after $max_attempts attempts: ${command[*]}"
    return 1
}

# Retry a function with exponential backoff
# Usage: retry_function <max_attempts> <delay> <function_name> [args...]
retry_function() {
    local max_attempts="$1"
    local base_delay="$2"
    local func_name="$3"
    shift 3
    local args=("$@")
    
    local attempt=1
    local delay="$base_delay"
    
    while [ $attempt -le $max_attempts ]; do
        log_info "Attempt $attempt/$max_attempts: $func_name"
        
        if "$func_name" "${args[@]}"; then
            return 0
        fi
        
        if [ $attempt -lt $max_attempts ]; then
            log_warn "Function failed, retrying in ${delay}s..."
            sleep "$delay"
            delay=$((delay * 2))  # Exponential backoff
        fi
        
        ((attempt++)) || true
    done
    
    log_error "Function failed after $max_attempts attempts: $func_name"
    return 1
}

# Wait for a condition to be true
# Usage: wait_for_condition <timeout> <interval> <condition_command>
wait_for_condition() {
    local timeout="$1"
    local interval="$2"
    shift 2
    local condition=("$@")
    
    local elapsed=0
    
    while [ $elapsed -lt $timeout ]; do
        if "${condition[@]}"; then
            return 0
        fi
        
        sleep "$interval"
        elapsed=$((elapsed + interval))
    done
    
    log_error "Condition not met within ${timeout}s: ${condition[*]}"
    return 1
}

# Wait for a service to be ready
# Usage: wait_for_service <url> <timeout> <interval>
wait_for_service() {
    local url="$1"
    local timeout="${2:-60}"
    local interval="${3:-5}"
    
    wait_for_condition "$timeout" "$interval" curl -sf "$url" >/dev/null
}

# Wait for a file to exist
# Usage: wait_for_file <file_path> <timeout> <interval>
wait_for_file() {
    local file_path="$1"
    local timeout="${2:-60}"
    local interval="${3:-5}"
    
    wait_for_condition "$timeout" "$interval" test -f "$file_path"
}

