// Package network provides SSH client and retry utilities.
package network

import (
	"context"
	"math"
	"time"
)

// RetryConfig defines retry behavior parameters.
type RetryConfig struct {
	MaxAttempts  int
	InitialDelay time.Duration
	MaxDelay     time.Duration
	Multiplier   float64
}

// DefaultRetryConfig returns a default retry configuration.
func DefaultRetryConfig() RetryConfig {
	return RetryConfig{
		MaxAttempts:  3,
		InitialDelay: 1 * time.Second,
		MaxDelay:     30 * time.Second,
		Multiplier:   2.0,
	}
}

// Retry executes a function with exponential backoff retry logic.
func Retry(ctx context.Context, cfg RetryConfig, fn func() error) error {
	var lastErr error
	delay := cfg.InitialDelay

	for attempt := 0; attempt < cfg.MaxAttempts; attempt++ {
		err := fn()
		if err == nil {
			return nil
		}
		lastErr = err

		if attempt < cfg.MaxAttempts-1 {
			select {
			case <-ctx.Done():
				return ctx.Err()
			case <-time.After(delay):
				delay = time.Duration(math.Min(
					float64(delay)*cfg.Multiplier,
					float64(cfg.MaxDelay),
				))
			}
		}
	}

	return lastErr
}

// RetryWithBackoff provides a convenient wrapper for common retry scenarios
func RetryWithBackoff(ctx context.Context, maxAttempts int, operation func() error) error {
	cfg := RetryConfig{
		MaxAttempts:  maxAttempts,
		InitialDelay: 200 * time.Millisecond,
		MaxDelay:     2 * time.Second,
		Multiplier:   2.0,
	}
	return Retry(ctx, cfg, operation)
}

// RetryForNetworkOperations is optimized for network-related operations
func RetryForNetworkOperations(ctx context.Context, operation func() error) error {
	cfg := RetryConfig{
		MaxAttempts:  5,
		InitialDelay: 200 * time.Millisecond,
		MaxDelay:     5 * time.Second,
		Multiplier:   1.5,
	}
	return Retry(ctx, cfg, operation)
}
