package config

import (
	"testing"
	"time"

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

func TestValidateDefaults(t *testing.T) {
	cfg := WalConfig{}
	err := cfg.Validate()
	require.NoError(t, err, "default WalConfig should pass validation")

	d := Defaults()
	assert.Equal(t, 500*time.Microsecond, d.GroupCommitDelay)
	assert.Equal(t, d.MaxSegmentSize, cfg.MaxSegmentSize, "MaxSegmentSize should be defaulted")
	assert.Equal(t, d.BlockSize, cfg.BlockSize, "BlockSize should be defaulted")
	assert.Equal(t, d.SyncMode, cfg.SyncMode, "SyncMode should be defaulted")
	assert.Equal(t, d.MaxBatchEntries, cfg.MaxBatchEntries, "MaxBatchEntries should be defaulted")
	assert.Equal(t, d.MaxBatchSize, cfg.MaxBatchSize, "MaxBatchSize should be defaulted")
	assert.Equal(t, d.GroupCommitDelay, cfg.GroupCommitDelay, "GroupCommitDelay should be defaulted")
	assert.Equal(t, d.MaxKeyBytes, cfg.MaxKeyBytes, "MaxKeyBytes should be defaulted")
	assert.Equal(t, d.MaxInlineValue, cfg.MaxInlineValue, "MaxInlineValue should be defaulted")
	assert.Equal(t, d.MemTableSize, cfg.MemTableSize, "MemTableSize should be defaulted")
	assert.Equal(t, d.MaxImmutableCount, cfg.MaxImmutableCount, "MaxImmutableCount should be defaulted")
}

func TestValidateGroupCommitDelay(t *testing.T) {
	tests := []struct {
		name  string
		delay time.Duration
		want  string
	}{
		{name: "negative delay", delay: -time.Microsecond, want: "GroupCommitDelay"},
		{name: "ten milliseconds rejected", delay: 10 * time.Millisecond, want: "GroupCommitDelay"},
		{name: "above ten milliseconds rejected", delay: 11 * time.Millisecond, want: "GroupCommitDelay"},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			cfg := Defaults()
			cfg.GroupCommitDelay = tt.delay

			err := cfg.Validate()
			require.Error(t, err)
			assert.Contains(t, err.Error(), tt.want)
		})
	}
}

func TestValidateSegmentTooSmall(t *testing.T) {
	cfg := WalConfig{MaxSegmentSize: 1024}
	err := cfg.Validate()
	require.Error(t, err, "MaxSegmentSize=1024 should fail validation")
	assert.Contains(t, err.Error(), "too small")
}
