package utils

import (
	"context"
	"fmt"
	"math/rand"
	"sync/atomic"
	"testing"
	"time"

	"github.com/stretchr/testify/assert"
)

var index int32 = 0

var defaultConfig = Config{
	step: 10,
}

type testSegmentService struct{}

func (t *testSegmentService) GetSegment(ctx context.Context, step int32) (*Segment, error) {
	for {
		old := index
		newIndex := index + step
		if atomic.CompareAndSwapInt32(&index, old, newIndex) {
			return NewSegment(old, step), nil
		}
	}

}

func Test_Single(t *testing.T) {
	g := NewIdGenerator(defaultConfig, &testSegmentService{})
	last := int32(0)
	for i := int32(1); i < 2000; i++ {
		value, err := g.Next(context.TODO())
		assert.NoError(t, err)
		assert.Less(t, last, value)
		last = value
	}
}

func Test_Distributed(t *testing.T) {
	for i := 0; i < 7; i++ {
		time.Sleep(time.Millisecond * 2)
		go func() {
			g := NewIdGenerator(defaultConfig, &testSegmentService{})
			for j := int32(1); j < 30; j++ {
				value, err := g.Next(context.TODO())
				assert.NoError(t, err)
				assert.NotEmpty(t, value)
				fmt.Println(value)
				time.Sleep(time.Millisecond * time.Duration(rand.Intn(50)))
			}
		}()
	}

	time.Sleep(time.Second * 2)
}
