package main

import (
	"fmt"
	"log"
	"net/http"
	"os"
	"strings"
	"sync"
	"sync/atomic"
	"time"
)

func main() {
	// Read URLs from environment variable
	urlsEnv := os.Getenv("TARGET_URLS")
	if urlsEnv == "" {
		log.Fatal("TARGET_URLS environment variable is not set")
	}

	// Parse comma-delimited URLs
	urls := strings.Split(urlsEnv, ",")
	for i := range urls {
		urls[i] = strings.TrimSpace(urls[i])
	}

	if len(urls) == 0 {
		log.Fatal("No URLs provided")
	}

	fmt.Printf("Starting load test on %d URLs\n", len(urls))
	fmt.Println("URLs:", urls)
	fmt.Println("Press Ctrl+C to stop\n")

	// Counters
	var (
		totalRequests uint64
		successCount  uint64
		errorCount    uint64
	)

	// WaitGroup to track all goroutines
	var wg sync.WaitGroup

	// Start time
	startTime := time.Now()

	// Spawn a goroutine for each URL
	for _, url := range urls {
		wg.Add(1)
		go func(targetURL string) {
			defer wg.Done()

			client := &http.Client{Timeout: time.Second}
			for {
				resp, err := client.Get(targetURL)
				atomic.AddUint64(&totalRequests, 1)

				if err != nil {
					fmt.Printf("error: %s => %v\n", targetURL, err)
					atomic.AddUint64(&errorCount, 1)
					continue
				}

				_ = resp.Body.Close()

				if resp.StatusCode >= 200 && resp.StatusCode < 300 {
					atomic.AddUint64(&successCount, 1)
				} else {
					fmt.Printf("bad status: %s => %d\n", targetURL, resp.StatusCode)
					atomic.AddUint64(&errorCount, 1)
				}
			}
		}(url)
	}

	// Progress reporter
	go func() {
		ticker := time.NewTicker(1 * time.Second)
		defer ticker.Stop()

		for {
			<-ticker.C
			elapsed := time.Since(startTime).Seconds()
			requests := atomic.LoadUint64(&totalRequests)
			success := atomic.LoadUint64(&successCount)
			errors := atomic.LoadUint64(&errorCount)
			fmt.Printf("Elapsed: %.0fs | Requests: %d | Success: %d | Errors: %d | Rate: %.0f req/s\n",
				elapsed, requests, success, errors, float64(requests)/elapsed)
		}
	}()

	// Wait for all goroutines (runs forever until killed)
	wg.Wait()
}
