package handlers_test

import (
	"testing"

	"github.com/fiskerinc/cloud-services/pkg/db/queries/mocks"
	"github.com/fiskerinc/cloud-services/pkg/testhelper"

	"github.com/fiskerinc/cloud-services/services/attendant/handlers"
	"github.com/fiskerinc/cloud-services/services/attendant/services"

	"github.com/fiskerinc/cloud-services/pkg/common"
	"github.com/fiskerinc/cloud-services/pkg/redis/tester"
)

func TestGetFileKey(t *testing.T) {
	testVIN := "JH4KA7680RC01"
	trexKey := "1:JH4KA7680RC01"
	hmiKey := "2:JH4KA7680RC01"
	fileCache1 := "fileid:b7d94be8c94062cf"
	fileCache2 := "fileid:83165a80c940e8b3"
	testPayload := `{"file_ids": ["b7d94be8c94062cf","83165a80c940e8b3"]}`
	testDBQuery := []common.FileKey{
		{
			FileID: "b7d94be8c94062cf",
			Auth:   []byte("AuthValue"),
			Key:    []byte("KeyValue"),
			Nonce:  []byte("NonceValue"),
		},
		{
			FileID: "83165a80c940e8b3",
			Auth:   []byte("AuthValue2"),
			Key:    []byte("KeyValue2"),
			Nonce:  []byte("NonceValue2"),
		},
	}

	mockRedis := tester.NewRedisMock()
	services.SetRedisClientPool(tester.NewMockClientPool(mockRedis))
	mockFileKeys := &mocks.MockFileKeys{}
	mockDB := &services.DB{}
	mockDB.SetFileKeys(mockFileKeys)

	tests := []AttendentRouteTestCase{
		{
			Name: "[TREX] From DB",
			RedisTestCase: tester.RedisTestCase{
				Device:      common.TRex,
				DeviceKey:   testVIN,
				PayloadData: testPayload,
				ExpectedCaches: map[string]tester.ExpiringCacheResult{
					fileCache1: {
						Value:   `{"file_id":"b7d94be8c94062cf","key":"S2V5VmFsdWU=","auth":"QXV0aFZhbHVl","nonce":"Tm9uY2VWYWx1ZQ=="}`,
						Expires: 86400,
					},
					fileCache2: {
						Value:   `{"file_id":"83165a80c940e8b3","key":"S2V5VmFsdWUy","auth":"QXV0aFZhbHVlMg==","nonce":"Tm9uY2VWYWx1ZTI="}`,
						Expires: 86400,
					},
				},
				ExpectedMessages: map[string]string{
					trexKey: `{"handler":"filekeys","data":[{"file_id":"b7d94be8c94062cf","key":"S2V5VmFsdWU=","auth":"QXV0aFZhbHVl","nonce":"Tm9uY2VWYWx1ZQ=="},{"file_id":"83165a80c940e8b3","key":"S2V5VmFsdWUy","auth":"QXV0aFZhbHVlMg==","nonce":"Tm9uY2VWYWx1ZTI="}]}`,
				},
			},
			MockFileKeysSelect: testDBQuery,
			MockFileKeysError:  nil,
		},
		{
			Name: "[HMI] From DB",
			RedisTestCase: tester.RedisTestCase{
				Device:      common.HMI,
				DeviceKey:   testVIN,
				PayloadData: testPayload,
				ExpectedCaches: map[string]tester.ExpiringCacheResult{
					fileCache1: {
						Value:   `{"file_id":"b7d94be8c94062cf","key":"S2V5VmFsdWU=","auth":"QXV0aFZhbHVl","nonce":"Tm9uY2VWYWx1ZQ=="}`,
						Expires: 86400,
					},
					fileCache2: {
						Value:   `{"file_id":"83165a80c940e8b3","key":"S2V5VmFsdWUy","auth":"QXV0aFZhbHVlMg==","nonce":"Tm9uY2VWYWx1ZTI="}`,
						Expires: 86400,
					},
				},
				ExpectedMessages: map[string]string{
					hmiKey: `{"handler":"filekeys","data":[{"file_id":"b7d94be8c94062cf","key":"S2V5VmFsdWU=","auth":"QXV0aFZhbHVl","nonce":"Tm9uY2VWYWx1ZQ=="},{"file_id":"83165a80c940e8b3","key":"S2V5VmFsdWUy","auth":"QXV0aFZhbHVlMg==","nonce":"Tm9uY2VWYWx1ZTI="}]}`,
				},
			},
			MockFileKeysSelect: testDBQuery,
			MockFileKeysError:  nil,
		},
	}

	schemaTester := testhelper.NewSchemaTestHelper(t, schemaToTRex)
	for _, test := range tests {
		t.Run(test.Name, func(t *testing.T) {
			mockRedis.Reset()
			test.SetupRedis(mockRedis)
			mockFileKeys.GetMultiResponse = test.MockFileKeysSelect
			mockFileKeys.Error = test.MockFileKeysError

			err := handlers.GetFileKeys(mockDB, test.Device, test.DeviceKey, []byte(test.PayloadData))

			test.CheckHandlerError(t, test.Name, err)
			test.Validate(t, test.Name, mockRedis)

			for _, m := range test.ExpectedMessages {
				schemaTester.ValidateSchemaObject(test.Name, []byte(m))
			}
		})
	}
}

func BenchmarkGetFileKey(b *testing.B) {
	db := services.GetDB()
	vin := "1F15K3R45N1234567"
	id := []byte(`{"file_ids": ["b7d94be8c94062cf","83165a80c940e8b3"]}`)

	for n := 0; n < b.N; n++ {
		err := handlers.GetFileKeys(db, common.TRex, vin, id)
		if err != nil {
			b.Error(err)
		}
	}
}
