package main

import (
	"context"
	"testing"
	"time"

	"go.uber.org/goleak"
)

// TestMain verifies no goroutines leak in any test in this package
func TestMain(m *testing.M) {
	os.Exit(goleak.VerifyTestMain(m))
}

// This test will FAIL because ProcessWithLeak leaks a goroutine
func TestProcessWithLeak(t *testing.T) {
	t.Skip("Skipping because this test demonstrates a leak")

	defer goleak.VerifyNone(t)

	ProcessWithLeak("test data")

	// Test will fail here because goroutine is still running
}

// This test will PASS because ProcessWithContext properly manages goroutines
func TestProcessWithContext(t *testing.T) {
	defer goleak.VerifyNone(t)

	ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second)
	defer cancel()

	ProcessWithContext(ctx, "test data")

	// Give goroutine time to finish
	time.Sleep(200 * time.Millisecond)

	// goleak will verify no goroutines are leaked
}

// This test will PASS because ProcessWithWaitGroup waits for completion
func TestProcessWithWaitGroup(t *testing.T) {
	defer goleak.VerifyNone(t)

	ProcessWithWaitGroup("test data")

	// WaitGroup ensures goroutine completes, so no leak
}

// Test worker pool with proper cleanup
func TestWorkerPool(t *testing.T) {
	defer goleak.VerifyNone(t)

	ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second)
	defer cancel()

	jobs := make(chan string, 5)

	// Start worker pool
	done := make(chan struct{})
	go func() {
		WorkerPool(ctx, jobs, 3)
		close(done)
	}()

	// Send some jobs
	jobs <- "job1"
	jobs <- "job2"
	jobs <- "job3"
	close(jobs)

	// Wait for workers to complete
	<-done

	// All goroutines should be cleaned up
}

// Example of ignoring expected background goroutines
func TestWithIgnoredGoroutines(t *testing.T) {
	defer goleak.VerifyNone(t,
		// Ignore current goroutine
		goleak.IgnoreCurrent(),
	)

	// Test code that might have expected background goroutines
}
