package prototool_test

import (
	"testing"

	"gitlab.com/gitlab-org/cluster-integration/gitlab-agent/v18/internal/tool/prototool"
	"gitlab.com/gitlab-org/cluster-integration/gitlab-agent/v18/internal/tool/testing/mock_prototool"
	"gitlab.com/gitlab-org/cluster-integration/gitlab-agent/v18/internal/tool/testing/testhelpers"
)

func TestValidation_Valid(t *testing.T) {
	bin := make([]byte, 256)
	for i := range 256 {
		bin[i] = byte(i)
	}
	tests := []testhelpers.ValidTestcase{
		{
			Name: "HeaderValues one empty",
			Valid: &prototool.HeaderValues{
				Value: [][]byte{
					{},
				},
			},
		},
		{
			Name: "HeaderKV special key chars with :",
			Valid: &prototool.HeaderKV{
				Key: []byte(":" + mock_prototool.ValidHeaderName()),
				Value: &prototool.HeaderValues{
					Value: [][]byte{
						{},
					},
				},
			},
		},
		{
			Name: "HeaderKV special key chars",
			Valid: &prototool.HeaderKV{
				Key: []byte(mock_prototool.ValidHeaderName()),
				Value: &prototool.HeaderValues{
					Value: [][]byte{
						{},
					},
				},
			},
		},
		{
			Name:  "empty QueryValues",
			Valid: &prototool.QueryValues{},
		},
		{
			Name: "QueryValues with empty element",
			Valid: &prototool.QueryValues{
				Value: [][]byte{
					{},
				},
			},
		},
		{
			Name: "QueryValues with non-empty element",
			Valid: &prototool.QueryValues{
				Value: [][]byte{
					bin,
				},
			},
		},
		{
			Name: "QueryKV",
			Valid: &prototool.QueryKV{
				Key:   bin,
				Value: &prototool.QueryValues{},
			},
		},
		{
			Name: "HeaderValues special chars",
			Valid: &prototool.HeaderValues{
				Value: [][]byte{
					[]byte(mock_prototool.ValidHeaderValue()),
				},
			},
		},
	}
	testhelpers.AssertValid(t, tests)
}

func TestValidation_Invalid(t *testing.T) {
	tests := []testhelpers.InvalidTestcase{
		{
			ErrString: "validation error: value: value must contain at least 1 item(s)",
			Invalid: &prototool.HeaderValues{
				Value: nil,
			},
		},
		{
			ErrString: "validation error: value: value must contain at least 1 item(s)",
			Invalid: &prototool.HeaderValues{
				Value: [][]byte{},
			},
		},
		{
			ErrString: "validation errors:\n - key: value must match regex pattern `^:?[0-9a-zA-Z!#$%&'*+-.^_|~`]+$`\n - value: value is required",
			Invalid:   &prototool.HeaderKV{},
		},
		{
			ErrString: "validation errors:\n - method: value length must be at least 1 bytes\n - url_path: value length must be at least 1 bytes",
			Invalid:   &prototool.HttpRequest{},
		},
		{
			ErrString: "validation errors:\n - key: value length must be at least 1 bytes\n - value: value is required",
			Invalid:   &prototool.QueryKV{},
		},
	}

	// TODO add validation here once the bytes.matches works as required. See https://github.com/bufbuild/protovalidate/issues/268.

	// \\x00-\\x08\\x0A-\\x1F\\x7F
	//invalidBytes := []byte{
	//	0, 1, 2, 3, 4, 5, 6, 7, 8,
	//	0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
	//	0x7F,
	//}
	//for _, invalidByte := range invalidBytes {
	//	tests = append(tests, testhelpers.InvalidTestcase{
	//		ErrString: "validation error: value[0]: value must match regex pattern `^[^\\x00-\\x08\\x0A-\\x1F\\x7F]*$`",
	//		Invalid: &prototool.HeaderValues{
	//			Value: [][]byte{
	//				{invalidByte},
	//			},
	//		},
	//	})
	//}
	testhelpers.AssertInvalid(t, tests)
}
