// +build integration

package logic

import (
	"context"
	"testing"

	"github.com/aws/aws-sdk-go/aws"

	"code.justin.tv/live/autohost/internal/hosting/auth"
	"code.justin.tv/live/autohost/lib"
	"github.com/stretchr/testify/require"
)

func TestGetSettings_Success(t *testing.T) {
	testEnv := newTestEnv(t, &Params{
		Auth: auth.NewAllowAllStub(),
	})
	l := testEnv.logic

	channelID := NewRandomUserID()
	strategy := lib.AutohostStrategyOrdered

	ctx, cancel := getContextWithTimeout()
	defer cancel()
	_, err := l.UpdateSettings(ctx, channelID, channelID, &lib.UpdateSettingsInput{
		Enabled:             boolPtr(true),
		TeamHost:            boolPtr(true),
		Strategy:            &strategy,
		DeprioritizeVodcast: boolPtr(true),
	})
	require.NoError(t, err)

	ctx, cancel = getContextWithTimeout()
	defer cancel()
	settings, err := l.GetSettings(ctx, channelID, channelID)
	require.NoError(t, err)
	require.NotNil(t, settings)
	require.True(t, settings.Enabled)
	require.True(t, settings.TeamHost)
	require.Equal(t, strategy, settings.Strategy)
}

func TestGetSettings_ReadsFromCache(t *testing.T) {
	testEnv := newTestEnv(t, &Params{
		Auth: auth.NewAllowAllStub(),
	})
	l := testEnv.logic
	cache := testEnv.memcachedCache
	userID := NewRandomUserID()

	// Set settings in the cache, and not in the DB.
	ctx, cancel := getContextWithTimeout()
	defer cancel()
	err := cache.SetSettings(ctx, userID, &lib.Settings{
		Enabled:  true,
		TeamHost: true,
	})
	require.NoError(t, err)

	// Verify that GetSettings reads from the cache.
	ctx, cancel = getContextWithTimeout()
	defer cancel()
	settings, err := l.GetSettings(ctx, userID, userID)
	require.NoError(t, err)
	require.NotNil(t, settings)
	require.True(t, settings.Enabled)
	require.True(t, settings.TeamHost)
}

func TestGetSettings_ReadsFromDbOnCacheMiss(t *testing.T) {
	testEnv := newTestEnv(t, &Params{
		Auth: auth.NewAllowAllStub(),
	})
	l := testEnv.logic
	storage := testEnv.storageClient
	userID := NewRandomUserID()

	// Set settings in the DB, but not in the cache.
	ctx, cancel := getContextWithTimeout()
	defer cancel()
	_, err := storage.UpdateSettings(ctx, userID, &lib.UpdateSettingsInput{
		Enabled:  aws.Bool(true),
		TeamHost: aws.Bool(true),
	})
	require.NoError(t, err)

	// Verify that GetSettings reads from the DB on cache miss.
	ctx, cancel = getContextWithTimeout()
	defer cancel()
	fetchedSettings, err := l.GetSettings(ctx, userID, userID)
	require.NoError(t, err)
	require.NotNil(t, fetchedSettings)
	require.True(t, fetchedSettings.Enabled)
	require.True(t, fetchedSettings.TeamHost)
}

// Verify that defaults are correct.
func TestGetSettings_Defaults(t *testing.T) {
	testEnv := newTestEnv(t, &Params{
		Auth: auth.NewAllowAllStub(),
	})
	l := testEnv.logic

	channelID := NewRandomUserID()
	settings, err := l.GetSettings(context.Background(), channelID, channelID)
	require.NoError(t, err)
	require.NotNil(t, settings)
	require.Equal(t, lib.AutohostStrategyRandom, settings.Strategy)
	require.Equal(t, lib.CanBeRaidedByAll, settings.CanBeRaidedBy)
}

func TestGetSettings_Unauthorized(t *testing.T) {
	testEnv := newTestEnv(t, &Params{
		Auth: auth.NewDenyAllStub(),
	})
	l := testEnv.logic

	channelID := NewRandomUserID()
	settings, err := l.GetSettings(context.Background(), channelID, channelID)
	require.Error(t, err)
	require.Nil(t, settings)
}
