package handlers_test

import (
	"github.com/fiskerinc/cloud-services/services/attendant/handlers"
	"github.com/fiskerinc/cloud-services/services/attendant/services"
	"testing"

	"github.com/fiskerinc/cloud-services/pkg/common"
	"github.com/fiskerinc/cloud-services/pkg/db/queries/mocks"
	"github.com/fiskerinc/cloud-services/pkg/redis/tester"
	"github.com/fiskerinc/cloud-services/pkg/testhelper"
	"github.com/pkg/errors"
)

func TestGetAllEccKeys(t *testing.T) {
	testVIN := "JH4KA7680RC01"
	trexKey := "1:JH4KA7680RC01"

	pk11 := common.NewBinaryHex([]byte("testprivkey11"))
	pk12 := common.NewBinaryHex([]byte("testprivkey12"))
	pk13 := common.NewBinaryHex([]byte("testprivkey13"))
	pk21 := common.NewBinaryHex([]byte("testprivkey21"))
	pk22 := common.NewBinaryHex([]byte("testprivkey22"))
	pk23 := common.NewBinaryHex([]byte("testprivkey23"))

	testDBQuery := []common.ECCKeys{
		{
			ECU:      "testecu1",
			PrivKey1: &pk11,
			PrivKey2: &pk12,
			PrivKey3: &pk13,
		},
		{
			ECU:      "testecu2",
			PrivKey1: &pk21,
			PrivKey2: &pk22,
			PrivKey3: &pk23,
		},
		{
			ECU:      "PDU",
			PrivKey1: &pk21,
			PrivKey2: &pk22,
			PrivKey3: &pk23,
		},
	}

	mockRedis := tester.NewRedisMock()
	services.SetRedisClientPool(tester.NewMockClientPool(mockRedis))
	mockEccKeys := &mocks.MockEccKeys{}
	mockDB := &services.DB{}
	mockDB.SetECCKeys(mockEccKeys)

	tests := []AttendentRouteTestCase{
		{
			Name: "[TREX] From DB, no car update id",
			RedisTestCase: tester.RedisTestCase{
				Device:    common.TRex,
				DeviceKey: testVIN,
				ExpectedMessages: map[string]string{
					trexKey: `{"handler":"ecc_keys","data":[{"ecu":"testecu1","level_1":"74657374707269766b65793131","level_2":"74657374707269766b65793132","level_3":"74657374707269766b65793133"},{"ecu":"testecu2","level_1":"74657374707269766b65793231","level_2":"74657374707269766b65793232","level_3":"74657374707269766b65793233"},{"ecu":"OBC","level_1":"74657374707269766b65793231","level_2":"74657374707269766b65793232","level_3":"74657374707269766b65793233"}]}`,
				},
			},
			MockEccKeysSelect: testDBQuery,
		},
		{
			Name: "[TREX] From DB, with car update id",
			RedisTestCase: tester.RedisTestCase{
				Device:    common.TRex,
				DeviceKey: testVIN,
				ExpectedMessages: map[string]string{
					trexKey: `{"handler":"ecc_keys","data":[{"ecu":"testecu1","level_1":"74657374707269766b65793131","level_2":"74657374707269766b65793132","level_3":"74657374707269766b65793133"},{"ecu":"testecu2","level_1":"74657374707269766b65793231","level_2":"74657374707269766b65793232","level_3":"74657374707269766b65793233"},{"ecu":"OBC","level_1":"74657374707269766b65793231","level_2":"74657374707269766b65793232","level_3":"74657374707269766b65793233"}]}`,
				},
				PayloadData: `{"car_update_id":10000}`,
			},
			MockEccKeysSelect: testDBQuery,
		},
		{
			Name: "Error",
			RedisTestCase: tester.RedisTestCase{
				Device:        common.TRex,
				DeviceKey:     testVIN,
				ExpectedError: "something went wrong",
			},
			MockEccKeysSelect: nil,
		},
	}

	schemaTester := testhelper.NewSchemaTestHelper(t, schemaToTRex)
	for _, test := range tests {
		t.Run(test.Name, func(t *testing.T) {
			mockRedis.Reset()
			test.SetupRedis(mockRedis)
			mockEccKeys.MockListResponse = test.MockEccKeysSelect

			if test.Name == "Error" {
				mockEccKeys.Error = errors.New("something went wrong")
			} else {
				mockEccKeys.Error = nil
			}

			err := handlers.GetAllEccKeys(mockDB, 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))
			}
		})
	}
}
