package taskscaler

import (
	"context"
	"testing"
	"time"

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

	dummy "gitlab.com/gitlab-org/fleeting/fleeting/plugin/fleeting-plugin-dummy"
)

func BenchmarkSchedule(b *testing.B) {
	ts, err := New(context.Background(), &dummy.InstanceGroup{}, WithScheduleTimezone("UTC"))
	require.NoError(b, err)

	err = ts.ConfigureSchedule(
		Schedule{
			Periods:   []string{"* * * * *"},
			IdleCount: 5,
		},
		Schedule{
			Periods:   []string{"* * * * mon,sun"},
			IdleCount: 10,
		},
		Schedule{
			Periods:   []string{"5 2 * * wed"},
			IdleCount: 20,
		},
	)
	require.NoError(b, err)

	b.ReportAllocs()
	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		ts.(*taskscaler).schedules.active(time.Date(2020, time.February, 1, 0, 0, 0, 0, time.Local))
	}
}

func TestSchedule(t *testing.T) {
	ts, err := New(context.Background(), &dummy.InstanceGroup{}, WithScheduleTimezone("UTC"))
	require.NoError(t, err)

	err = ts.ConfigureSchedule(
		Schedule{
			Periods:   []string{"1 * * * *"},
			IdleCount: 5,
		},
		Schedule{
			Periods:   []string{"* * * * mon,sun"},
			IdleCount: 10,
		},
		Schedule{
			Periods:   []string{"5 2 * * wed"},
			IdleCount: 20,
		},
		Schedule{
			Timezone:  "America/Los_Angeles",
			Periods:   []string{"0 0 * * fri"},
			IdleCount: 50,
		},
	)
	require.NoError(t, err)

	taskscalerImpl := ts.(*taskscaler)
	assert.Equal(t, taskscalerImpl.schedules.active(time.Now()), taskscalerImpl.active, "active schedule should be immmediately set")

	losAngelesTz, err := time.LoadLocation("America/Los_Angeles")
	require.NoError(t, err)

	tests := []struct {
		date                 time.Time
		expectedMinIdleCount int
	}{
		{date: time.Date(2020, time.February, 5, 2, 5, 0, 0, time.UTC), expectedMinIdleCount: 20},
		{date: time.Date(2020, time.February, 3, 0, 0, 0, 0, time.UTC), expectedMinIdleCount: 10},
		{date: time.Date(2020, time.February, 3, 23, 59, 59, 0, time.UTC), expectedMinIdleCount: 10},
		{date: time.Date(2020, time.February, 5, 2, 1, 0, 0, time.UTC), expectedMinIdleCount: 5},
		{date: time.Date(2020, time.February, 5, 2, 8, 0, 0, time.UTC), expectedMinIdleCount: 0},
		{date: time.Date(2020, time.February, 7, 0, 0, 0, 0, time.UTC), expectedMinIdleCount: 0},
		{date: time.Date(2020, time.February, 7, 8, 0, 0, 0, time.UTC), expectedMinIdleCount: 50}, // equivalent to los angeles time below
		{date: time.Date(2020, time.February, 7, 0, 0, 0, 0, losAngelesTz), expectedMinIdleCount: 50},
	}

	for _, tc := range tests {
		min := ts.(*taskscaler).schedules.active(tc.date).IdleCount
		assert.Equal(t, tc.expectedMinIdleCount, min)
	}
}
