package queries_test

import (
	"testing"

	"github.com/fiskerinc/cloud-services/pkg/common"
	"github.com/fiskerinc/cloud-services/pkg/db/queries"
	"github.com/fiskerinc/cloud-services/pkg/testhelper"
	th "github.com/fiskerinc/cloud-services/pkg/testhelper"
	"github.com/fiskerinc/cloud-services/pkg/validator"
)

const testFileID string = "07a4ed515543d4d8"
const testFileIDNonExistent string = "3edffbecef53734d"
const testFileKey string = "TEST_KEYTEST_KEYTEST_KEYTEST_KEY"
const testNouce string = "NOUNCENOUNCE"

var fk queries.FileKeysInterface

func TestStructValidation(t *testing.T) {
	type TestCase struct {
		Name          string
		Struct        common.FileKey
		ExpectedError string
	}

	tests := []TestCase{
		{
			Name:   "No values",
			Struct: common.FileKey{},
			ExpectedError: `Key: 'FileKey.FileID' Error:Field validation for 'FileID' failed on the 'required' tag
Key: 'FileKey.Key' Error:Field validation for 'Key' failed on the 'required' tag
Key: 'FileKey.Auth' Error:Field validation for 'Auth' failed on the 'required' tag
Key: 'FileKey.Nonce' Error:Field validation for 'Nonce' failed on the 'required' tag`,
		},
		{
			Name: "Bad file id",
			Struct: common.FileKey{
				FileID: "XXXXXXXXXXXXXXXX",
				Key:    []byte("12345678901234561234567890123456"),
				Auth:   []byte("12345"),
				Nonce:  []byte("123456789012"),
			},
			ExpectedError: `Key: 'FileKey.FileID' Error:Field validation for 'FileID' failed on the 'hexadecimal' tag`,
		},
		{
			Name: "Bad file id 2",
			Struct: common.FileKey{
				FileID: "74fe7f75a9f59f3",
				Key:    []byte("12345678901234561234567890123456"),
				Auth:   []byte("12345"),
				Nonce:  []byte("123456789012"),
			},
			ExpectedError: `Key: 'FileKey.FileID' Error:Field validation for 'FileID' failed on the 'len' tag`,
		},
		{
			Name: "Good",
			Struct: common.FileKey{
				FileID: "074fe7f75a9f59f3",
				Key:    []byte("12345678901234561234567890123456"),
				Auth:   []byte("12345"),
				Nonce:  []byte("123456789012"),
			},
			ExpectedError: `Key: 'FileKey.FileID' Error:Field validation for 'FileID' failed on the 'len' tag`,
		},
	}

	for _, test := range tests {
		err := validator.ValidateStruct(test.Struct)
		if err != nil && err.Error() != test.ExpectedError {
			t.Errorf(testhelper.TestErrorTemplate, test.Name, test.ExpectedError, err.Error())
		}
	}
}

func TestFileKeysIntegration(t *testing.T) {
	t.Skip()
	fk = &queries.FileKeys{}

	fileKeysInsert(t)
	fileKeysGet(t)
	fileKeysDelete(t)

	fk = nil
}

func fileKeysInsert(t *testing.T) {
	_, err := fk.Insert(common.FileKey{})
	expectedError := `Key: 'FileKey.FileID' Error:Field validation for 'FileID' failed on the 'required' tag
Key: 'FileKey.Key' Error:Field validation for 'Key' failed on the 'required' tag
Key: 'FileKey.Auth' Error:Field validation for 'Auth' failed on the 'required' tag
Key: 'FileKey.Nonce' Error:Field validation for 'Nonce' failed on the 'required' tag`
	if err != nil && err.Error() != expectedError {
		t.Errorf(th.TestErrorTemplate, "Bad insert", expectedError, err)
	} else if err == nil {
		t.Errorf(th.TestErrorTemplate, "Bad insert", "Validation errors", err)
	}

	result, err := fk.Insert(common.FileKey{
		FileID: testFileID,
		Key:    []byte(testFileKey),
		Auth:   []byte(testFileKey + "AUTH"),
		Nonce:  []byte(testNouce),
	})
	if err != nil {
		t.Errorf(th.TestErrorTemplate, "Good insert", "no error", err)
	}
	if result.RowsAffected() != 1 {
		t.Errorf(th.TestErrorTemplate, "Good insert", "1 row", result.RowsAffected())
	}
}

func fileKeysGet(t *testing.T) {
	filekey, err := fk.Get(testFileIDNonExistent)
	expectedError := "non-existent key"
	if err != nil && err.Error() != expectedError {
		t.Errorf(th.TestErrorTemplate, "Get Non-existent", expectedError, err)
	} else if err == nil {
		t.Errorf(th.TestErrorTemplate, "Get Non-existent", "Results errors", err)
	}
	if filekey != nil {
		t.Errorf(th.TestErrorTemplate, "Get Non-existent", "nil", filekey)
	}

	filekey, err = fk.Get(testFileID)
	if err != nil {
		t.Errorf(th.TestErrorTemplate, "Get", "get errors", err)
	}
	if string(filekey.Key) != testFileKey {
		t.Errorf(th.TestErrorTemplate, "Get", testFileKey, filekey.Key)
	}
	if string(filekey.Auth) != testFileKey+"AUTH" {
		t.Errorf(th.TestErrorTemplate, "Get", testFileKey+"AUTH", filekey.Auth)
	}
	if string(filekey.Nonce) != testNouce {
		t.Errorf(th.TestErrorTemplate, "Get", testNouce, filekey.Nonce)
	}
}

func fileKeysDelete(t *testing.T) {
	result, err := fk.Delete(testFileIDNonExistent)
	if err != nil {
		t.Errorf(th.TestErrorTemplate, "Delete non-existing file id", "no error", err)
	} else if result.RowsAffected() > 0 {
		t.Errorf(th.TestErrorTemplate, "Delete non-existing file id", "no rows", result.RowsAffected())
	}

	result, err = fk.Delete(testFileID)
	if err != nil {
		t.Errorf(th.TestErrorTemplate, "Delete file id", "no error", err)
	}
	if result.RowsAffected() != 1 {
		t.Errorf(th.TestErrorTemplate, "Delete file id", 1, result.RowsAffected())
	}
}
