package unstable_plan

import (
	"testing"

	"github.com/google/go-cmp/cmp"
	"github.com/samber/lo"
	"github.com/stretchr/testify/assert"
)

func TestCalculateSuggestedPlan(t *testing.T) {
	svc := NewService(nil, 0, 0)

	type testCase struct {
		name string
		// Inputs
		stmts []*Model
		// Outputs
		computedStmts map[string]*Model
	}

	testCases := []testCase{
		{
			name: "plan count is 1, no suggested plan",
			stmts: []*Model{
				{
					SchemaName:    "schema_1",
					Digest:        "digest_1",
					AggMaxLatency: 1,
					AggMinLatency: 1,
					AggPlanCount:  1,
				},
			},
			computedStmts: map[string]*Model{
				"schema_1___digest_1": {
					SchemaName:    "schema_1",
					Digest:        "digest_1",
					AggMaxLatency: 1,
					AggMinLatency: 1,
					AggPlanCount:  1,

					M:                0,
					N:                1,
					HasSuggestedPlan: lo.ToPtr(false),
					Impact:           "",
				},
			},
		},
		{
			name: "has suggested plan, high impact",
			stmts: []*Model{
				{
					SchemaName:    "schema_1",
					Digest:        "digest_1",
					AggMaxLatency: 999000000000,
					AggMinLatency: 1000000000,
					AggPlanCount:  10,
				},
			},
			computedStmts: map[string]*Model{
				"schema_1___digest_1": {
					SchemaName:    "schema_1",
					Digest:        "digest_1",
					AggMaxLatency: 999000000000,
					AggMinLatency: 1000000000,
					AggPlanCount:  10,

					M:                998,
					N:                999,
					HasSuggestedPlan: lo.ToPtr(true),
					Impact:           ImpactHigh,
				},
			},
		},
		{
			name: "multiple statements",
			stmts: []*Model{
				{
					SchemaName:    "schema_1",
					Digest:        "digest_1",
					AggMaxLatency: 1,
					AggMinLatency: 1,
					AggPlanCount:  1,
				},
				{
					SchemaName:    "schema_2",
					Digest:        "digest_2",
					AggMaxLatency: 999000000000,
					AggMinLatency: 1000000000,
					AggPlanCount:  10,
				},
			},
			computedStmts: map[string]*Model{
				"schema_1___digest_1": {
					SchemaName:    "schema_1",
					Digest:        "digest_1",
					AggMaxLatency: 1,
					AggMinLatency: 1,
					AggPlanCount:  1,

					M:                0,
					N:                1,
					HasSuggestedPlan: lo.ToPtr(false),
					Impact:           "",
				},
				"schema_2___digest_2": {
					SchemaName:    "schema_2",
					Digest:        "digest_2",
					AggMaxLatency: 999000000000,
					AggMinLatency: 1000000000,
					AggPlanCount:  10,

					M:                998,
					N:                999,
					HasSuggestedPlan: lo.ToPtr(true),
					Impact:           ImpactHigh,
				},
			},
		},
	}

	for _, tc := range testCases {
		t.Run(tc.name, func(t *testing.T) {
			res, err := svc.calculateSuggestedPlan(tc.stmts)
			assert.Nil(t, err)
			diff := cmp.Diff(tc.computedStmts, res)
			assert.Empty(t, diff)
			//// reflect.DeepEqual will deref pointers automatically.
			//assert.True(t, reflect.DeepEqual(tc.computedStmts, res))
		})
	}
}
