package src_test

import (
	"testing"
	"testing/synctest"
	"time"
)

// section: basic
func Test_Synctest_Basic(t *testing.T) {
	synctest.Test(t, func(t *testing.T) {
		start := time.Now()

		// This would normally take 5 seconds
		// but with synctest, it's instant!
		time.Sleep(5 * time.Second)

		elapsed := time.Since(start)

		// Inside the bubble, the fake clock shows 5 seconds passed
		if elapsed < 5*time.Second {
			t.Errorf("expected 5s elapsed, got %v", elapsed)
		}

		t.Logf("Fake time elapsed: %v", elapsed)
		t.Log("5 second sleep completed instantly!")
	})
}

// section: basic

// section: wait
func Test_Synctest_Wait(t *testing.T) {
	synctest.Test(t, func(t *testing.T) {
		results := make(chan int, 3)

		// Start goroutines that sleep for different durations
		go func() {
			time.Sleep(1 * time.Second)
			results <- 1
		}()
		go func() {
			time.Sleep(2 * time.Second)
			results <- 2
		}()
		go func() {
			time.Sleep(3 * time.Second)
			results <- 3
		}()

		// Wait blocks until all goroutines are idle
		synctest.Wait()

		// All goroutines have completed their sleep
		// Collect results
		var got []int
		for i := 0; i < 3; i++ {
			got = append(got, <-results)
		}

		t.Logf("Results received in order: %v", got)
	})
}

// section: wait

// section: ticker
func Test_Synctest_Ticker(t *testing.T) {
	synctest.Test(t, func(t *testing.T) {
		ticker := time.NewTicker(100 * time.Millisecond)
		defer ticker.Stop()

		count := 0
		done := make(chan struct{})

		go func() {
			for range ticker.C {
				count++
				if count >= 5 {
					close(done)
					return
				}
			}
		}()

		// Wait for ticker to fire 5 times
		<-done

		if count != 5 {
			t.Errorf("expected 5 ticks, got %d", count)
		}

		// This would take 500ms in real time
		// but completes instantly with synctest
		t.Logf("Processed %d ticker events instantly!", count)
	})
}

// section: ticker
