package spells

import (
	"context"
	"encoding/json"
	"os"
	"reflect"
	"testing"

	"gitea.maximumdirect.net/eric/notarius/internal/modules/dnd"
)

type normalizerFixtureSet struct {
	Cases []normalizerFixtureCase `json:"cases"`
}

type normalizerFixtureCase struct {
	Name                  string        `json:"name"`
	Input                 dnd.SpellList `json:"input"`
	Output                dnd.SpellList `json:"output"`
	DiagnosticReasonCodes []string      `json:"diagnostic_reason_codes"`
}

func TestNormalizeAcceptedFixtures(t *testing.T) {
	data, err := os.ReadFile("testdata/normalizer_accepted_cases.json")
	if err != nil {
		t.Fatalf("read fixture: %v", err)
	}
	var fixtures normalizerFixtureSet
	if err := json.Unmarshal(data, &fixtures); err != nil {
		t.Fatalf("decode fixture: %v", err)
	}
	if len(fixtures.Cases) == 0 {
		t.Fatal("fixture set is empty")
	}

	for _, fixture := range fixtures.Cases {
		t.Run(fixture.Name, func(t *testing.T) {
			result, err := newNormalizer(t).Normalize(context.Background(), normalizeRequestWithSource(fixture.Input, sourceDocument(2)))
			if err != nil {
				t.Fatalf("Normalize() error = %v, want nil", err)
			}
			if !reflect.DeepEqual(result.Value, fixture.Output) {
				t.Fatalf("normalized value = %#v, want %#v", result.Value, fixture.Output)
			}

			gotReasonCodes := make([]string, 0, len(result.Diagnostics))
			for _, diagnostic := range result.Diagnostics {
				gotReasonCodes = append(gotReasonCodes, diagnostic.ReasonCode)
			}
			if !reflect.DeepEqual(gotReasonCodes, fixture.DiagnosticReasonCodes) {
				t.Fatalf("diagnostic reason codes = %#v, want %#v", gotReasonCodes, fixture.DiagnosticReasonCodes)
			}
		})
	}
}
