package candidatejson

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

type testCandidate struct {
	Items []string `json:"items"`
}

func TestCandidateJSON(t *testing.T) {
	input := testCandidate{Items: []string{"one", "two"}}
	content, err := EncodeCandidate("test candidate", input)
	if err != nil {
		t.Fatalf("EncodeCandidate() error = %v", err)
	}
	if !json.Valid(content) {
		t.Fatalf("EncodeCandidate() = %q, want JSON", content)
	}
	for _, test := range []struct {
		name    string
		content []byte
		want    testCandidate
		wantErr string
	}{
		{name: "typed round trip", content: content, want: input},
		{name: "unknown field", content: []byte(`{"items":[],"unexpected":true}`), wantErr: "unknown field"},
		{name: "malformed JSON", content: []byte(`{"items":`), wantErr: "decode test candidate"},
		{name: "trailing value", content: []byte(`{"items":[]} {}`), wantErr: "multiple JSON values"},
	} {
		t.Run(test.name, func(t *testing.T) {
			got, err := DecodeCandidate[testCandidate]("test candidate", test.content)
			if test.wantErr != "" {
				if err == nil || !strings.Contains(err.Error(), test.wantErr) {
					t.Fatalf("DecodeCandidate() error = %v, want %q", err, test.wantErr)
				}
				return
			}
			if err != nil || !reflect.DeepEqual(got, test.want) {
				t.Fatalf("DecodeCandidate() = %#v, %v; want %#v", got, err, test.want)
			}
		})
	}
}
