//go:build !yaegi

package cleanup

import (
	"sync"
	"sync/atomic"
	"testing"
	"time"
)

// Mock logger for testing
type mockLogger struct {
	logs     []string
	errLogs  []string
	debugLog []string
	mu       sync.Mutex
}

func (m *mockLogger) Logf(format string, args ...interface{}) {
	m.mu.Lock()
	defer m.mu.Unlock()
	m.logs = append(m.logs, format)
}

func (m *mockLogger) ErrorLogf(format string, args ...interface{}) {
	m.mu.Lock()
	defer m.mu.Unlock()
	m.errLogs = append(m.errLogs, format)
}

func (m *mockLogger) DebugLogf(format string, args ...interface{}) {
	m.mu.Lock()
	defer m.mu.Unlock()
	m.debugLog = append(m.debugLog, format)
}

func (m *mockLogger) getLogCount() int {
	m.mu.Lock()
	defer m.mu.Unlock()
	return len(m.logs)
}

// BackgroundTask tests
func TestNewBackgroundTask(t *testing.T) {
	logger := &mockLogger{}
	var wg sync.WaitGroup
	runCount := 0

	task := NewBackgroundTask("test-task", 100*time.Millisecond, func() {
		runCount++
	}, logger, &wg)

	if task == nil {
		t.Fatal("Expected NewBackgroundTask to return non-nil")
	}

	if task.name != "test-task" {
		t.Errorf("Expected name 'test-task', got '%s'", task.name)
	}

	if task.interval != 100*time.Millisecond {
		t.Errorf("Expected interval 100ms, got %v", task.interval)
	}

	if task.IsRunning() {
		t.Error("Expected task to not be running initially")
	}
}

func TestBackgroundTask_Start(t *testing.T) {
	logger := &mockLogger{}
	runCount := int32(0)

	task := NewBackgroundTask("test-task", 50*time.Millisecond, func() {
		atomic.AddInt32(&runCount, 1)
	}, logger)

	task.Start()

	if !task.IsRunning() {
		t.Error("Expected task to be running after Start()")
	}

	// Wait for at least 2 executions
	time.Sleep(120 * time.Millisecond)

	task.Stop()

	count := atomic.LoadInt32(&runCount)
	if count < 2 {
		t.Errorf("Expected at least 2 executions, got %d", count)
	}
}

func TestBackgroundTask_Stop(t *testing.T) {
	logger := &mockLogger{}
	task := NewBackgroundTask("test-task", 100*time.Millisecond, func() {}, logger)

	task.Start()
	time.Sleep(50 * time.Millisecond)
	task.Stop()

	if task.IsRunning() {
		t.Error("Expected task to not be running after Stop()")
	}

	// Calling Stop again should not panic
	task.Stop()
}

func TestBackgroundTask_DoubleStart(t *testing.T) {
	logger := &mockLogger{}
	task := NewBackgroundTask("test-task", 100*time.Millisecond, func() {}, logger)

	task.Start()
	logCountBefore := logger.getLogCount()

	// Second start should be ignored
	task.Start()

	logCountAfter := logger.getLogCount()
	if logCountAfter <= logCountBefore {
		t.Error("Expected log message about task already running")
	}

	task.Stop()
}

func TestBackgroundTask_ExecuteWithPanic(t *testing.T) {
	logger := &mockLogger{}
	panicCount := int32(0)

	task := NewBackgroundTask("panic-task", 50*time.Millisecond, func() {
		count := atomic.AddInt32(&panicCount, 1)
		if count == 1 {
			panic("test panic")
		}
	}, logger)

	task.Start()
	time.Sleep(120 * time.Millisecond)
	task.Stop()

	// Task should recover from panic and continue
	finalCount := atomic.LoadInt32(&panicCount)
	if finalCount < 2 {
		t.Errorf("Expected task to continue after panic, got %d executions", finalCount)
	}

	stats := task.GetStats()
	if stats["errorCount"].(int64) < 1 {
		t.Error("Expected error count to be at least 1")
	}
}

func TestBackgroundTask_GetStats(t *testing.T) {
	logger := &mockLogger{}
	runCount := int32(0)

	task := NewBackgroundTask("test-task", 50*time.Millisecond, func() {
		atomic.AddInt32(&runCount, 1)
	}, logger)

	task.Start()
	time.Sleep(120 * time.Millisecond)
	task.Stop()

	stats := task.GetStats()

	if stats["name"] != "test-task" {
		t.Errorf("Expected name 'test-task', got %v", stats["name"])
	}

	if !stats["isRunning"].(bool) == true {
		// Task should be stopped
	}

	if stats["runCount"].(int64) < 2 {
		t.Errorf("Expected runCount >= 2, got %v", stats["runCount"])
	}
}

func TestBackgroundTask_WithWaitGroup(t *testing.T) {
	logger := &mockLogger{}
	var wg sync.WaitGroup
	runCount := int32(0)

	task := NewBackgroundTask("test-task", 50*time.Millisecond, func() {
		atomic.AddInt32(&runCount, 1)
	}, logger, &wg)

	task.Start()

	// Wait for task to start
	time.Sleep(100 * time.Millisecond)

	// Stop and wait
	done := make(chan bool)
	go func() {
		task.Stop()
		wg.Wait()
		close(done)
	}()

	select {
	case <-done:
		// Success
	case <-time.After(2 * time.Second):
		t.Error("Timeout waiting for task to stop")
	}
}

// TaskRegistry tests
func TestNewTaskRegistry(t *testing.T) {
	logger := &mockLogger{}
	registry := NewTaskRegistry(logger, 10)

	if registry == nil {
		t.Fatal("Expected NewTaskRegistry to return non-nil")
	}

	if registry.maxTasks != 10 {
		t.Errorf("Expected maxTasks 10, got %d", registry.maxTasks)
	}

	if registry.GetTaskCount() != 0 {
		t.Error("Expected initial task count to be 0")
	}
}

func TestTaskRegistry_RegisterTask(t *testing.T) {
	logger := &mockLogger{}
	registry := NewTaskRegistry(logger, 10)

	task := NewBackgroundTask("test-task", 100*time.Millisecond, func() {}, logger)
	err := registry.RegisterTask("test-task", task)

	if err != nil {
		t.Errorf("Expected no error, got %v", err)
	}

	if registry.GetTaskCount() != 1 {
		t.Error("Expected task count to be 1")
	}
}

func TestTaskRegistry_RegisterTask_Duplicate(t *testing.T) {
	logger := &mockLogger{}
	registry := NewTaskRegistry(logger, 10)

	task1 := NewBackgroundTask("test-task", 100*time.Millisecond, func() {}, logger)
	task2 := NewBackgroundTask("test-task", 100*time.Millisecond, func() {}, logger)

	err1 := registry.RegisterTask("test-task", task1)
	if err1 != nil {
		t.Errorf("Expected no error on first registration, got %v", err1)
	}

	err2 := registry.RegisterTask("test-task", task2)
	if err2 == nil {
		t.Error("Expected error when registering duplicate task")
	}
}

func TestTaskRegistry_RegisterTask_Nil(t *testing.T) {
	logger := &mockLogger{}
	registry := NewTaskRegistry(logger, 10)

	err := registry.RegisterTask("test-task", nil)
	if err == nil {
		t.Error("Expected error when registering nil task")
	}
}

func TestTaskRegistry_RegisterTask_MaxLimit(t *testing.T) {
	logger := &mockLogger{}
	registry := NewTaskRegistry(logger, 2)

	task1 := NewBackgroundTask("task1", 100*time.Millisecond, func() {}, logger)
	task2 := NewBackgroundTask("task2", 100*time.Millisecond, func() {}, logger)
	task3 := NewBackgroundTask("task3", 100*time.Millisecond, func() {}, logger)

	registry.RegisterTask("task1", task1)
	registry.RegisterTask("task2", task2)
	err := registry.RegisterTask("task3", task3)

	if err == nil {
		t.Error("Expected error when exceeding max tasks")
	}
}

func TestTaskRegistry_UnregisterTask(t *testing.T) {
	logger := &mockLogger{}
	registry := NewTaskRegistry(logger, 10)

	task := NewBackgroundTask("test-task", 100*time.Millisecond, func() {}, logger)
	registry.RegisterTask("test-task", task)

	if registry.GetTaskCount() != 1 {
		t.Error("Expected task count to be 1")
	}

	registry.UnregisterTask("test-task")

	if registry.GetTaskCount() != 0 {
		t.Error("Expected task count to be 0 after unregister")
	}
}

func TestTaskRegistry_UnregisterTask_Running(t *testing.T) {
	logger := &mockLogger{}
	registry := NewTaskRegistry(logger, 10)

	task := NewBackgroundTask("test-task", 100*time.Millisecond, func() {}, logger)
	registry.RegisterTask("test-task", task)
	task.Start()

	time.Sleep(50 * time.Millisecond)

	registry.UnregisterTask("test-task")

	if task.IsRunning() {
		t.Error("Expected task to be stopped after unregister")
	}
}

func TestTaskRegistry_GetTask(t *testing.T) {
	logger := &mockLogger{}
	registry := NewTaskRegistry(logger, 10)

	task := NewBackgroundTask("test-task", 100*time.Millisecond, func() {}, logger)
	registry.RegisterTask("test-task", task)

	retrieved, exists := registry.GetTask("test-task")
	if !exists {
		t.Error("Expected task to exist")
	}

	if retrieved != task {
		t.Error("Expected to retrieve the same task")
	}

	_, exists = registry.GetTask("non-existent")
	if exists {
		t.Error("Expected non-existent task to not exist")
	}
}

func TestTaskRegistry_StopAllTasks(t *testing.T) {
	logger := &mockLogger{}
	registry := NewTaskRegistry(logger, 10)

	task1 := NewBackgroundTask("task1", 100*time.Millisecond, func() {}, logger)
	task2 := NewBackgroundTask("task2", 100*time.Millisecond, func() {}, logger)

	registry.RegisterTask("task1", task1)
	registry.RegisterTask("task2", task2)

	task1.Start()
	task2.Start()

	time.Sleep(50 * time.Millisecond)

	registry.StopAllTasks()

	if task1.IsRunning() || task2.IsRunning() {
		t.Error("Expected all tasks to be stopped")
	}

	if registry.GetTaskCount() != 0 {
		t.Error("Expected task count to be 0 after StopAllTasks")
	}
}

func TestTaskRegistry_CreateSingletonTask(t *testing.T) {
	logger := &mockLogger{}
	registry := NewTaskRegistry(logger, 10)

	runCount := int32(0)
	task1, err1 := registry.CreateSingletonTask("singleton", 50*time.Millisecond, func() {
		atomic.AddInt32(&runCount, 1)
	}, logger)

	if err1 != nil {
		t.Errorf("Expected no error, got %v", err1)
	}

	if task1 == nil {
		t.Fatal("Expected task to be created")
	}

	if !task1.IsRunning() {
		t.Error("Expected task to be running")
	}

	// Try to create same task again
	task2, err2 := registry.CreateSingletonTask("singleton", 50*time.Millisecond, func() {
		atomic.AddInt32(&runCount, 1)
	}, logger)

	if err2 != nil {
		t.Errorf("Expected no error on second call, got %v", err2)
	}

	if task2 != task1 {
		t.Error("Expected to get the same task instance")
	}

	time.Sleep(120 * time.Millisecond)
	task1.Stop()

	if atomic.LoadInt32(&runCount) < 2 {
		t.Error("Expected task to have run multiple times")
	}
}

func TestTaskRegistry_GetAllTasks(t *testing.T) {
	logger := &mockLogger{}
	registry := NewTaskRegistry(logger, 10)

	task1 := NewBackgroundTask("task1", 100*time.Millisecond, func() {}, logger)
	task2 := NewBackgroundTask("task2", 100*time.Millisecond, func() {}, logger)

	registry.RegisterTask("task1", task1)
	registry.RegisterTask("task2", task2)

	allTasks := registry.GetAllTasks()

	if len(allTasks) != 2 {
		t.Errorf("Expected 2 tasks, got %d", len(allTasks))
	}

	if _, ok := allTasks["task1"]; !ok {
		t.Error("Expected task1 in results")
	}

	if _, ok := allTasks["task2"]; !ok {
		t.Error("Expected task2 in results")
	}
}

func TestTaskRegistry_GetStats(t *testing.T) {
	logger := &mockLogger{}
	registry := NewTaskRegistry(logger, 10)

	task := NewBackgroundTask("test-task", 100*time.Millisecond, func() {}, logger)
	registry.RegisterTask("test-task", task)
	task.Start()

	time.Sleep(50 * time.Millisecond)

	stats := registry.GetStats()

	if stats["totalTasks"].(int) != 1 {
		t.Errorf("Expected totalTasks 1, got %v", stats["totalTasks"])
	}

	if stats["runningTasks"].(int) != 1 {
		t.Errorf("Expected runningTasks 1, got %v", stats["runningTasks"])
	}

	if _, ok := stats["memory"]; !ok {
		t.Error("Expected memory stats")
	}

	task.Stop()
}

func TestGlobalTaskRegistry(t *testing.T) {
	// Reset before test
	ResetGlobalTaskRegistry()

	registry1 := GetGlobalTaskRegistry()
	registry2 := GetGlobalTaskRegistry()

	if registry1 != registry2 {
		t.Error("Expected singleton to return same instance")
	}

	// Cleanup
	ResetGlobalTaskRegistry()
}

func TestResetGlobalTaskRegistry(t *testing.T) {
	ResetGlobalTaskRegistry()

	registry := GetGlobalTaskRegistry()
	logger := &mockLogger{}
	task := NewBackgroundTask("test-task", 100*time.Millisecond, func() {}, logger)
	registry.RegisterTask("test-task", task)
	task.Start()

	time.Sleep(50 * time.Millisecond)

	ResetGlobalTaskRegistry()

	// Should get a new instance
	newRegistry := GetGlobalTaskRegistry()
	if newRegistry.GetTaskCount() != 0 {
		t.Error("Expected new registry to be empty")
	}
}

// TaskCircuitBreaker tests
func TestNewTaskCircuitBreaker(t *testing.T) {
	logger := &mockLogger{}
	cb := NewTaskCircuitBreaker(5, 30*time.Second, logger)

	if cb == nil {
		t.Fatal("Expected NewTaskCircuitBreaker to return non-nil")
	}

	if cb.failureThreshold != 5 {
		t.Errorf("Expected failureThreshold 5, got %d", cb.failureThreshold)
	}

	if cb.timeout != 30*time.Second {
		t.Errorf("Expected timeout 30s, got %v", cb.timeout)
	}

	if cb.GetState() != CircuitBreakerClosed {
		t.Error("Expected initial state to be closed")
	}
}

func TestTaskCircuitBreaker_CanCreateTask(t *testing.T) {
	logger := &mockLogger{}
	cb := NewTaskCircuitBreaker(3, 100*time.Millisecond, logger)

	err := cb.CanCreateTask("test-task")
	if err != nil {
		t.Errorf("Expected no error initially, got %v", err)
	}
}

func TestTaskCircuitBreaker_OnTaskFailure(t *testing.T) {
	logger := &mockLogger{}
	cb := NewTaskCircuitBreaker(3, 100*time.Millisecond, logger)

	// Record failures
	for i := 0; i < 3; i++ {
		cb.OnTaskFailure("test-task", nil)
	}

	// Circuit should be open
	if cb.GetState() != CircuitBreakerOpen {
		t.Error("Expected circuit breaker to be open after threshold failures")
	}

	// Should not be able to create task
	err := cb.CanCreateTask("test-task")
	if err == nil {
		t.Error("Expected error when circuit breaker is open")
	}
}

func TestTaskCircuitBreaker_OnTaskSuccess(t *testing.T) {
	logger := &mockLogger{}
	cb := NewTaskCircuitBreaker(5, 100*time.Millisecond, logger)

	cb.OnTaskFailure("test-task", nil)
	cb.OnTaskFailure("test-task", nil)

	cb.OnTaskSuccess("test-task")

	// Task-specific failures should be reset
	err := cb.CanCreateTask("test-task")
	if err != nil {
		t.Errorf("Expected no error after success, got %v", err)
	}
}

func TestTaskCircuitBreaker_Reset(t *testing.T) {
	logger := &mockLogger{}
	cb := NewTaskCircuitBreaker(2, 100*time.Millisecond, logger)

	cb.OnTaskFailure("test-task", nil)
	cb.OnTaskFailure("test-task", nil)

	if cb.GetState() != CircuitBreakerOpen {
		t.Error("Expected circuit breaker to be open")
	}

	cb.Reset()

	if cb.GetState() != CircuitBreakerClosed {
		t.Error("Expected circuit breaker to be closed after reset")
	}

	err := cb.CanCreateTask("test-task")
	if err != nil {
		t.Errorf("Expected no error after reset, got %v", err)
	}
}

func TestTaskCircuitBreaker_TimeoutRecovery(t *testing.T) {
	logger := &mockLogger{}
	cb := NewTaskCircuitBreaker(2, 100*time.Millisecond, logger)

	// Open circuit breaker
	cb.OnTaskFailure("test-task", nil)
	cb.OnTaskFailure("test-task", nil)

	if cb.GetState() != CircuitBreakerOpen {
		t.Error("Expected circuit breaker to be open")
	}

	// Wait for timeout
	time.Sleep(150 * time.Millisecond)

	// Circuit breaker should reset, but task-specific failures remain
	// Need to check with a different task name
	err := cb.CanCreateTask("different-task")
	if err != nil {
		t.Errorf("Expected no error for different task after timeout, got %v", err)
	}

	if cb.GetState() != CircuitBreakerClosed {
		t.Error("Expected circuit breaker to be closed after timeout")
	}

	// Original task still has too many failures
	err = cb.CanCreateTask("test-task")
	if err == nil {
		t.Error("Expected error for original task with too many failures")
	}
}

// TaskMemoryMonitor tests
func TestNewTaskMemoryMonitor(t *testing.T) {
	logger := &mockLogger{}
	registry := NewTaskRegistry(logger, 10)
	monitor := NewTaskMemoryMonitor(logger, registry)

	if monitor == nil {
		t.Fatal("Expected NewTaskMemoryMonitor to return non-nil")
	}

	if monitor.registry != registry {
		t.Error("Expected registry to be set")
	}

	if monitor.memoryThreshold != 1024*1024*1024 {
		t.Errorf("Expected default threshold 1GB, got %d", monitor.memoryThreshold)
	}
}

func TestTaskMemoryMonitor_SetMemoryThreshold(t *testing.T) {
	logger := &mockLogger{}
	registry := NewTaskRegistry(logger, 10)
	monitor := NewTaskMemoryMonitor(logger, registry)

	monitor.SetMemoryThreshold(512 * 1024 * 1024)

	stats := monitor.GetStats()
	if stats["memoryThreshold"].(uint64) != 512*1024*1024 {
		t.Error("Expected threshold to be updated")
	}
}

func TestTaskMemoryMonitor_StartStop(t *testing.T) {
	logger := &mockLogger{}
	registry := NewTaskRegistry(logger, 10)
	monitor := NewTaskMemoryMonitor(logger, registry)

	monitor.StartMonitoring()

	stats := monitor.GetStats()
	if !stats["isMonitoring"].(bool) {
		t.Error("Expected monitor to be running")
	}

	// Double start should be ignored
	monitor.StartMonitoring()

	monitor.StopMonitoring()

	stats = monitor.GetStats()
	if stats["isMonitoring"].(bool) {
		t.Error("Expected monitor to be stopped")
	}

	// Double stop should be safe
	monitor.StopMonitoring()
}

func TestTaskMemoryMonitor_GetStats(t *testing.T) {
	logger := &mockLogger{}
	registry := NewTaskRegistry(logger, 10)
	monitor := NewTaskMemoryMonitor(logger, registry)

	stats := monitor.GetStats()

	if _, ok := stats["isMonitoring"]; !ok {
		t.Error("Expected isMonitoring in stats")
	}

	if _, ok := stats["currentMemory"]; !ok {
		t.Error("Expected currentMemory in stats")
	}

	if _, ok := stats["memoryThreshold"]; !ok {
		t.Error("Expected memoryThreshold in stats")
	}
}

// WorkerPool tests
func TestNewWorkerPool(t *testing.T) {
	logger := &mockLogger{}
	pool := NewWorkerPool(4, 10, logger)

	if pool == nil {
		t.Fatal("Expected NewWorkerPool to return non-nil")
	}

	if pool.workers != 4 {
		t.Errorf("Expected 4 workers, got %d", pool.workers)
	}
}

func TestWorkerPool_DefaultWorkers(t *testing.T) {
	logger := &mockLogger{}
	pool := NewWorkerPool(0, 0, logger)

	// Should default to NumCPU
	if pool.workers <= 0 {
		t.Error("Expected positive number of workers")
	}
}

func TestWorkerPool_StartStop(t *testing.T) {
	logger := &mockLogger{}
	pool := NewWorkerPool(2, 5, logger)

	pool.Start()

	metrics := pool.GetMetrics()
	if !metrics["isRunning"].(bool) {
		t.Error("Expected worker pool to be running")
	}

	// Double start should be ignored
	pool.Start()

	pool.Stop()

	metrics = pool.GetMetrics()
	if metrics["isRunning"].(bool) {
		t.Error("Expected worker pool to be stopped")
	}

	// Double stop should be safe
	pool.Stop()
}

func TestWorkerPool_Submit(t *testing.T) {
	logger := &mockLogger{}
	pool := NewWorkerPool(2, 5, logger)

	pool.Start()
	defer pool.Stop()

	executed := int32(0)
	var wg sync.WaitGroup

	for i := 0; i < 3; i++ {
		wg.Add(1)
		err := pool.Submit(func() {
			defer wg.Done()
			atomic.AddInt32(&executed, 1)
		})

		if err != nil {
			t.Errorf("Expected no error submitting task, got %v", err)
		}
	}

	// Wait for tasks to complete
	done := make(chan bool)
	go func() {
		wg.Wait()
		close(done)
	}()

	select {
	case <-done:
		// Success
	case <-time.After(2 * time.Second):
		t.Error("Timeout waiting for tasks to complete")
	}

	if atomic.LoadInt32(&executed) != 3 {
		t.Errorf("Expected 3 tasks executed, got %d", atomic.LoadInt32(&executed))
	}
}

func TestWorkerPool_SubmitWhenStopped(t *testing.T) {
	logger := &mockLogger{}
	pool := NewWorkerPool(2, 5, logger)

	err := pool.Submit(func() {})
	if err == nil {
		t.Error("Expected error when submitting to stopped pool")
	}
}

func TestWorkerPool_TaskPanic(t *testing.T) {
	logger := &mockLogger{}
	pool := NewWorkerPool(2, 5, logger)

	pool.Start()
	defer pool.Stop()

	executed := int32(0)
	var wg sync.WaitGroup

	wg.Add(2)
	// Submit task that panics
	pool.Submit(func() {
		defer wg.Done()
		panic("test panic")
	})

	// Submit normal task
	pool.Submit(func() {
		defer wg.Done()
		atomic.AddInt32(&executed, 1)
	})

	// Wait for tasks
	done := make(chan bool)
	go func() {
		wg.Wait()
		close(done)
	}()

	select {
	case <-done:
		// Success
	case <-time.After(2 * time.Second):
		t.Error("Timeout waiting for tasks")
	}

	// tasksFailed is incremented in the worker's deferred recover(), which runs
	// AFTER the panicking task's own `defer wg.Done()`. wg.Wait() above can
	// therefore return before the failure is recorded — reading the counter
	// immediately is a race that flakes on slow/contended CI runners. Poll until
	// the failure lands (or time out).
	deadline := time.Now().Add(2 * time.Second)
	for pool.GetMetrics()["tasksFailed"].(int64) < 1 {
		if time.Now().After(deadline) {
			t.Error("Expected at least one failed task")
			break
		}
		time.Sleep(5 * time.Millisecond)
	}
}

func TestWorkerPool_GetMetrics(t *testing.T) {
	logger := &mockLogger{}
	pool := NewWorkerPool(2, 5, logger)

	pool.Start()
	defer pool.Stop()

	var wg sync.WaitGroup
	wg.Add(2)

	pool.Submit(func() {
		defer wg.Done()
		time.Sleep(10 * time.Millisecond)
	})

	pool.Submit(func() {
		defer wg.Done()
		time.Sleep(10 * time.Millisecond)
	})

	wg.Wait()

	metrics := pool.GetMetrics()

	if metrics["workers"].(int) != 2 {
		t.Errorf("Expected 2 workers, got %v", metrics["workers"])
	}

	if metrics["tasksProcessed"].(int64) != 2 {
		t.Errorf("Expected 2 processed tasks, got %v", metrics["tasksProcessed"])
	}

	if metrics["tasksQueued"].(int64) != 2 {
		t.Errorf("Expected 2 queued tasks, got %v", metrics["tasksQueued"])
	}
}

func TestWorkerPool_Concurrent(t *testing.T) {
	logger := &mockLogger{}
	pool := NewWorkerPool(4, 20, logger)

	pool.Start()
	defer pool.Stop()

	executed := int32(0)
	var wg sync.WaitGroup

	taskCount := 10
	for i := 0; i < taskCount; i++ {
		wg.Add(1)
		err := pool.Submit(func() {
			defer wg.Done()
			atomic.AddInt32(&executed, 1)
			time.Sleep(10 * time.Millisecond)
		})

		if err != nil {
			wg.Done()
			t.Errorf("Failed to submit task: %v", err)
		}
	}

	// Wait for all tasks
	done := make(chan bool)
	go func() {
		wg.Wait()
		close(done)
	}()

	select {
	case <-done:
		// Success
	case <-time.After(5 * time.Second):
		t.Error("Timeout waiting for concurrent tasks")
	}

	if atomic.LoadInt32(&executed) != int32(taskCount) {
		t.Errorf("Expected %d tasks executed, got %d", taskCount, atomic.LoadInt32(&executed))
	}
}
