package syncz

import (
	"context"
	"testing"
	"time"

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

func TestValueHolder_GetReturnsAfterSet(t *testing.T) {
	h := NewValueHolder[int64]()
	require.NoError(t, h.Set(1))
	id, err := h.Get(context.Background())
	require.NoError(t, err)
	assert.EqualValues(t, 1, id)
}

func TestValueHolder_TryGetReturnsAfterSet(t *testing.T) {
	h := NewValueHolder[int64]()
	_, ok := h.TryGet()
	require.False(t, ok)
	require.NoError(t, h.Set(1))
	id, ok := h.TryGet()
	require.True(t, ok)
	assert.EqualValues(t, 1, id)
}

func TestValueHolder_GetReturnsAfterConcurrentSet(t *testing.T) {
	h := NewValueHolder[int64]()
	go func() {
		assert.NoError(t, h.Set(1))
	}()
	id, err := h.Get(context.Background())
	require.NoError(t, err)
	assert.EqualValues(t, 1, id)
}

func TestValueHolder_GetTimesOut(t *testing.T) {
	h := NewValueHolder[int64]()
	ctx, cancel := context.WithTimeout(context.Background(), time.Millisecond)
	defer cancel()
	_, err := h.Get(ctx)
	assert.Equal(t, context.DeadlineExceeded, err)
}

func TestValueHolder_SetReturnsNoErrorOnSameID(t *testing.T) {
	h := NewValueHolder[int64]()
	require.NoError(t, h.Set(1))
	assert.NoError(t, h.Set(1))
}

func TestValueHolder_SetReturnsErrorOnDifferentID(t *testing.T) {
	h := NewValueHolder[int64]()
	require.NoError(t, h.Set(1))
	assert.EqualError(t, h.Set(2), "value is already set to a different value: old 1, new 2")
}
