package controllers

import "testing"

func ptr(s string) *string { return &s }

// The failure this guards is a real one: share_name "Tod Test 3" with an empty customer_label built
// the log group "/frontdoor//mtls/tod test 3-2120", which CloudWatch rejected after the stack had
// already created resources.
func TestValidateCreateNaming(t *testing.T) {
	cases := []struct {
		name    string
		req     CreateTcpShareReq
		wantErr bool
	}{
		{"v2 accepts a clean name", CreateTcpShareReq{NamingScheme: "v2", ShareName: "tod-test-3", CustomerLabel: "acme"}, false},
		{"v2 accepts mixed case", CreateTcpShareReq{NamingScheme: "v2", ShareName: "TodTest3", CustomerLabel: "Acme"}, false},
		{"v2 accepts a single character", CreateTcpShareReq{NamingScheme: "v2", ShareName: "a", CustomerLabel: "b"}, false},
		{"v2 rejects spaces in share_name", CreateTcpShareReq{NamingScheme: "v2", ShareName: "Tod Test 3", CustomerLabel: "acme"}, true},
		{"v2 rejects an empty customer_label", CreateTcpShareReq{NamingScheme: "v2", ShareName: "tod-test-3"}, true},
		{"v2 rejects an empty share_name", CreateTcpShareReq{NamingScheme: "v2", CustomerLabel: "acme"}, true},
		{"v2 rejects a leading hyphen", CreateTcpShareReq{NamingScheme: "v2", ShareName: "-tod", CustomerLabel: "acme"}, true},
		{"v2 rejects a trailing hyphen", CreateTcpShareReq{NamingScheme: "v2", ShareName: "tod-", CustomerLabel: "acme"}, true},
		{"v2 rejects a slash", CreateTcpShareReq{NamingScheme: "v2", ShareName: "tod/test", CustomerLabel: "acme"}, true},
		{"v2 rejects a pipe", CreateTcpShareReq{NamingScheme: "v2", ShareName: "tod|test", CustomerLabel: "acme"}, true},
		{"v2 rejects 64 characters", CreateTcpShareReq{NamingScheme: "v2", ShareName: strings64(), CustomerLabel: "acme"}, true},
		{"legacy ignores a dirty name", CreateTcpShareReq{NamingScheme: "", ShareName: "Tod Test 3"}, false},
		{"an unknown scheme is rejected", CreateTcpShareReq{NamingScheme: "v3", ShareName: "tod-test-3", CustomerLabel: "acme"}, true},
	}
	for _, tc := range cases {
		t.Run(tc.name, func(t *testing.T) {
			err := validateCreateNaming(tc.req)
			if tc.wantErr && err == nil {
				t.Fatalf("expected an error, got nil")
			}
			if !tc.wantErr && err != nil {
				t.Fatalf("expected no error, got %v", err)
			}
		})
	}
}

func TestValidateUpdateNaming(t *testing.T) {
	cases := []struct {
		name    string
		req     UpdateTcpShareReq
		wantErr bool
	}{
		{"an omitted name is not checked", UpdateTcpShareReq{}, false},
		{"a clean rename is accepted", UpdateTcpShareReq{ShareName: ptr("tod-test-4")}, false},
		{"a name with spaces is rejected", UpdateTcpShareReq{ShareName: ptr("Tod Test 4")}, true},
		{"a cleared name is rejected", UpdateTcpShareReq{ShareName: ptr("")}, true},
	}
	for _, tc := range cases {
		t.Run(tc.name, func(t *testing.T) {
			err := validateUpdateNaming(tc.req)
			if tc.wantErr && err == nil {
				t.Fatalf("expected an error, got nil")
			}
			if !tc.wantErr && err != nil {
				t.Fatalf("expected no error, got %v", err)
			}
		})
	}
}

// strings64 returns a 64 character name, one over the pattern's limit.
func strings64() string {
	s := make([]byte, 64)
	for i := range s {
		s[i] = 'a'
	}
	return string(s)
}
