package correlation

import (
	"context"
	"testing"

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

func TestExtractFromContext(t *testing.T) {
	require := require.New(t)

	tests := []struct {
		name string
		ctx  context.Context
		want string
	}{
		{"missing", context.Background(), ""},
		{"set", context.WithValue(context.Background(), keyCorrelationID, "CORRELATION_ID"), "CORRELATION_ID"},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			require.Equal(tt.want, ExtractFromContext(tt.ctx))
		})
	}
}

func TestExtractFromContextOrGenerate(t *testing.T) {
	require := require.New(t)

	tests := []struct {
		name string
		ctx  context.Context
		want string
	}{
		{"missing", context.Background(), ""},
		{"set", context.WithValue(context.Background(), keyCorrelationID, "CORRELATION_ID"), "CORRELATION_ID"},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			if tt.want == "" { // want a random one
				require.NotEmpty(ExtractFromContextOrGenerate(tt.ctx))
			} else {
				require.Equal(tt.want, ExtractFromContextOrGenerate(tt.ctx))
			}
		})
	}
}

func TestContextWithCorrelation(t *testing.T) {
	require := require.New(t)

	tests := []struct {
		name          string
		ctx           context.Context
		correlationID string
		wantValue     string
	}{
		{
			name:          "value",
			ctx:           context.Background(),
			correlationID: "CORRELATION_ID",
			wantValue:     "CORRELATION_ID",
		},
		{
			name:          "empty",
			ctx:           context.Background(),
			correlationID: "",
			wantValue:     "",
		},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			got := ContextWithCorrelation(tt.ctx, tt.correlationID)
			gotValue := got.Value(keyCorrelationID)
			require.Equal(tt.wantValue, gotValue)
		})
	}
}

func TestExtractClientNameFromContext(t *testing.T) {
	require := require.New(t)

	tests := []struct {
		name string
		ctx  context.Context
		want string
	}{
		{"missing", context.Background(), ""},
		{"set", context.WithValue(context.Background(), keyClientName, "CLIENT_NAME"), "CLIENT_NAME"},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			require.Equal(tt.want, ExtractClientNameFromContext(tt.ctx))
		})
	}
}

func TestContextWithClientName(t *testing.T) {
	require := require.New(t)

	tests := []struct {
		name       string
		ctx        context.Context
		clientName string
		wantValue  string
	}{
		{
			name:       "value",
			ctx:        context.Background(),
			clientName: "CLIENT_NAME",
			wantValue:  "CLIENT_NAME",
		},
		{
			name:       "empty",
			ctx:        context.Background(),
			clientName: "",
			wantValue:  "",
		},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			got := ContextWithClientName(tt.ctx, tt.clientName)
			gotValue := got.Value(keyClientName)
			require.Equal(tt.wantValue, gotValue)
		})
	}
}
