package fieldpermissions

import "testing"

func TestAccessCoherent(t *testing.T) {
	for _, test := range []struct {
		name       string
		read, edit bool
		want       bool
	}{
		{name: "neither", want: true},
		{name: "read only", read: true, want: true},
		{name: "read and edit", read: true, edit: true, want: true},
		{name: "edit without read", edit: true, want: false},
	} {
		t.Run(test.name, func(t *testing.T) {
			if got := AccessCoherent(test.read, test.edit); got != test.want {
				t.Fatalf("AccessCoherent(%t, %t) = %t, want %t", test.read, test.edit, got, test.want)
			}
		})
	}
}

func TestSplitFieldReference(t *testing.T) {
	tests := []struct {
		name       string
		objectName string
		rawField   string
		wantObject string
		wantField  string
	}{
		{"simple", "Account", "Secret__c", "Account", "Secret__c"},
		{"qualified", "Account", "Account.Secret__c", "Account", "Secret__c"},
		{"trimmed", " Account ", " Account.Secret__c ", "Account", "Secret__c"},
		{"empty", "Account", "", "Account", ""},
		{"mismatched_object_kept_for_validation", "Account", "Contact.Secret__c", "Contact", "Secret__c"},
	}
	for _, tc := range tests {
		t.Run(tc.name, func(t *testing.T) {
			gotObject, gotField := SplitFieldReference(tc.objectName, tc.rawField)
			if gotObject != tc.wantObject || gotField != tc.wantField {
				t.Fatalf("SplitFieldReference(%q, %q) = (%q, %q); want (%q, %q)",
					tc.objectName, tc.rawField, gotObject, gotField, tc.wantObject, tc.wantField)
			}
		})
	}
}

func TestQualifiedField(t *testing.T) {
	tests := []struct {
		name       string
		objectName string
		rawField   string
		want       string
	}{
		{"simple", "Account", "Secret__c", "Account.Secret__c"},
		{"qualified", "Account", "Account.Secret__c", "Account.Secret__c"},
		{"mismatched_object_uses_sobject_type", "Account", "Contact.Secret__c", "Account.Secret__c"},
	}
	for _, tc := range tests {
		t.Run(tc.name, func(t *testing.T) {
			if got := QualifiedField(tc.objectName, tc.rawField); got != tc.want {
				t.Fatalf("QualifiedField(%q, %q) = %q; want %q", tc.objectName, tc.rawField, got, tc.want)
			}
		})
	}
}

func TestMatchesFieldReference(t *testing.T) {
	tests := []struct {
		name       string
		objectName string
		rowField   string
		requested  string
		want       bool
	}{
		{"simple_matches_simple", "Account", "Secret__c", "Secret__c", true},
		{"simple_matches_qualified", "Account", "Secret__c", "Account.Secret__c", true},
		{"qualified_matches_simple", "Account", "Account.Secret__c", "Secret__c", true},
		{"case_insensitive", "Account", "account.secret__c", "ACCOUNT.SECRET__C", true},
		{"mismatched_object_rejected", "Account", "Contact.Secret__c", "Secret__c", false},
		{"different_field_rejected", "Account", "Name", "Secret__c", false},
	}
	for _, tc := range tests {
		t.Run(tc.name, func(t *testing.T) {
			if got := MatchesFieldReference(tc.objectName, tc.rowField, tc.requested); got != tc.want {
				t.Fatalf("MatchesFieldReference(%q, %q, %q) = %v; want %v",
					tc.objectName, tc.rowField, tc.requested, got, tc.want)
			}
		})
	}
}
