package wire

import (
	"encoding/json"
	"reflect"
	"testing"
)

func TestErrorEnvelopeByteShape(t *testing.T) {
	cases := []struct {
		name string
		body []SFError
		want string
	}{
		{name: "plain", body: SFErrorResponse(SFCodeInvalidRequest, "bad request"), want: `[{"errorCode":"INVALID_REQUEST","message":"bad request"}]`},
		{name: "fields", body: SFErrorWithFields(SFCodeInvalidField, "bad field", "Name", "OwnerId"), want: `[{"errorCode":"INVALID_FIELD","message":"bad field","fields":["Name","OwnerId"]}]`},
		{name: "internal", body: SFGenericInternalErrorResponse(), want: `[{"errorCode":"INTERNAL_ERROR","message":"An internal server error occurred. Contact your system administrator."}]`},
	}
	for _, tc := range cases {
		t.Run(tc.name, func(t *testing.T) {
			got, err := json.Marshal(tc.body)
			if err != nil {
				t.Fatal(err)
			}
			if string(got) != tc.want {
				t.Fatalf("body = %s, want %s", got, tc.want)
			}
		})
	}
}

func TestMutationIdentifierCodes(t *testing.T) {
	if SFCodeInvalidID != "INVALID_ID" || SFCodeMalformedID != "MALFORMED_ID" {
		t.Fatalf("mutation identifier codes drifted: invalid=%q malformed=%q", SFCodeInvalidID, SFCodeMalformedID)
	}
}

func TestCreateFromSourceGuardMessageIsVersionedAndCanonical(t *testing.T) {
	const want = "Direct create of Case with a configured source-FK populated is not permitted. " +
		"Invoke one of the owning standard action endpoints instead: " +
		"/services/data/v59.0/actions/standard/Case.Escalate, " +
		"/services/data/v59.0/actions/standard/Lead.Convert"
	got := CreateFromSourceGuardMessage("v59.0", "Case", []string{"Lead.Convert", "Case.Escalate", "Lead.Convert"})
	if got != want {
		t.Fatalf("message = %q, want %q", got, want)
	}
}

func TestCreateFromSourceGuardMessageDefaultsVersion(t *testing.T) {
	const want = "Direct create of Case with a configured source-FK populated is not permitted. " +
		"Invoke the owning standard action endpoint instead: /services/data/v63.0/actions/standard/Case.Escalate"
	if got := CreateFromSourceGuardMessage(" ", "Case", []string{"Case.Escalate"}); got != want {
		t.Fatalf("message = %q, want %q", got, want)
	}
}

func TestValidationErrorEnvelope(t *testing.T) {
	status, body := ValidationErrorEnvelope(" Name, OwnerId, ", "invalid", SFCodeInvalidField)
	if status != 400 {
		t.Fatalf("status = %d, want 400", status)
	}
	want := []SFError{{ErrorCode: SFCodeInvalidField, Message: "invalid", Fields: []string{"Name", "OwnerId"}}}
	if !reflect.DeepEqual(body, want) {
		t.Fatalf("body = %#v, want %#v", body, want)
	}
}
