package zddc

import (
	"testing"
)

func TestValidatePattern(t *testing.T) {
	cases := []struct {
		pattern string
		ok      bool
	}{
		{"alice@example.com", true},
		{"*@example.com", true},
		{"alice@*", true},
		{"*", true},
		{"", false},
		{" alice@example.com", false},
		{"alice@example.com ", false},
		{"alice @example.com", false},
		{"alice@ex ample.com", false},
		{"alice@@example.com", false},
		{"@example.com", false},
		{"alice@", false},
		{"@", false},
	}
	for _, tc := range cases {
		t.Run(tc.pattern, func(t *testing.T) {
			err := ValidatePattern(tc.pattern)
			if tc.ok && err != nil {
				t.Errorf("ValidatePattern(%q) = %v, want nil", tc.pattern, err)
			}
			if !tc.ok && err == nil {
				t.Errorf("ValidatePattern(%q) = nil, want error", tc.pattern)
			}
		})
	}
}

func TestValidateFile(t *testing.T) {
	zf := ZddcFile{
		Title: "ok",
		ACL: ACLRules{Permissions: map[string]string{
			"good@example.com": "rwcd",
			"@bad":             "rwcd",
			"two@@ats":         "",
		}},
		Admins: []string{"@nobody"},
	}
	errs := ValidateFile(zf)
	// expect 3 errors
	if len(errs) != 3 {
		t.Fatalf("got %d errors, want 3: %+v", len(errs), errs)
	}
	wantFields := map[string]bool{
		"acl.permissions[\"@bad\"]":     false,
		"acl.permissions[\"two@@ats\"]": false,
		"admins[0]":                     false,
	}
	for _, e := range errs {
		if _, ok := wantFields[e.Field]; !ok {
			t.Errorf("unexpected error field: %q", e.Field)
			continue
		}
		wantFields[e.Field] = true
	}
	for f, seen := range wantFields {
		if !seen {
			t.Errorf("missing error for field %q", f)
		}
	}
}

func TestValidateProjectName(t *testing.T) {
	cases := []struct {
		name string
		ok   bool
	}{
		{"alpha", true},
		{"Alpha", true},
		{"a", true},
		{"a1", true},
		{"a-1", true},
		{"a_b", true},
		{"123-project", true},
		{"Site-3", true},
		{"", false},
		{".hidden", false},
		{"_template", false},
		{"-leading-dash", false},
		{"foo bar", false},
		{"foo/bar", false},
		{"foo\\bar", false},
		{"foo.bar", false},
		{"..", false},
		{".", false},
		{string(make([]byte, 65)), false},
	}
	for _, tc := range cases {
		t.Run(tc.name, func(t *testing.T) {
			err := ValidateProjectName(tc.name)
			if tc.ok && err != nil {
				t.Errorf("ValidateProjectName(%q) = %v, want nil", tc.name, err)
			}
			if !tc.ok && err == nil {
				t.Errorf("ValidateProjectName(%q) = nil, want error", tc.name)
			}
		})
	}
}

func TestValidateFileTitleLength(t *testing.T) {
	long := make([]byte, 201)
	for i := range long {
		long[i] = 'a'
	}
	zf := ZddcFile{Title: string(long)}
	errs := ValidateFile(zf)
	if len(errs) != 1 || errs[0].Field != "title" {
		t.Fatalf("expected one title-length error, got %+v", errs)
	}
}
