package main

import (
	"context"
	"fmt"
	"io"
	"net/http"
	"time"

	"github.com/hashicorp/go-retryablehttp"
)

func main() {
	// Create a retryable HTTP client with defaults
	client := retryablehttp.NewClient()

	// Configure retry behavior
	client.RetryMax = 3                           // Maximum retries
	client.RetryWaitMin = 1 * time.Second         // Minimum wait between retries
	client.RetryWaitMax = 30 * time.Second        // Maximum wait between retries
	client.HTTPClient.Timeout = 10 * time.Second  // Overall timeout

	// Make a simple GET request
	resp, err := client.Get("https://httpbin.org/get")
	if err != nil {
		fmt.Println("Error:", err)
		return
	}
	defer resp.Body.Close()

	body, _ := io.ReadAll(resp.Body)
	fmt.Println("Response:", string(body[:100])+"...")

	// POST with JSON body
	jsonBody := []byte(`{"name": "gopher", "language": "go"}`)
	resp, err = client.Post(
		"https://httpbin.org/post",
		"application/json",
		jsonBody,
	)
	if err != nil {
		fmt.Println("Error:", err)
		return
	}
	defer resp.Body.Close()
	fmt.Println("POST status:", resp.StatusCode)

	// Custom request with context
	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
	defer cancel()

	req, err := retryablehttp.NewRequestWithContext(
		ctx, http.MethodGet, "https://httpbin.org/headers", nil,
	)
	if err != nil {
		fmt.Println("Error creating request:", err)
		return
	}
	req.Header.Set("X-Custom-Header", "my-value")

	resp, err = client.Do(req)
	if err != nil {
		fmt.Println("Error:", err)
		return
	}
	defer resp.Body.Close()
	fmt.Println("Custom request status:", resp.StatusCode)

	// Custom retry policy - only retry on specific status codes
	client.CheckRetry = func(ctx context.Context, resp *http.Response, err error) (bool, error) {
		// Don't retry on context cancellation
		if ctx.Err() != nil {
			return false, ctx.Err()
		}
		// Retry on connection errors
		if err != nil {
			return true, nil
		}
		// Retry on 429 (rate limited) and 5xx errors
		if resp.StatusCode == 429 || resp.StatusCode >= 500 {
			return true, nil
		}
		return false, nil
	}

	// Custom backoff strategy
	client.Backoff = retryablehttp.LinearJitterBackoff

	// Disable logging (use nil logger)
	client.Logger = nil

	// Using the standard http.Client interface
	// Useful when you need to pass to libraries expecting *http.Client
	standardClient := client.StandardClient()
	resp, err = standardClient.Get("https://httpbin.org/get")
	if err != nil {
		fmt.Println("Error:", err)
		return
	}
	defer resp.Body.Close()
	fmt.Println("Standard client status:", resp.StatusCode)
}
