package itemoccurrences

import (
	"reflect"
	"testing"

	"gitea.maximumdirect.net/eric/notarius/internal/core/source"
	"gitea.maximumdirect.net/eric/notarius/internal/framework/contracts"
	"gitea.maximumdirect.net/eric/notarius/internal/framework/pipeline"
	"gitea.maximumdirect.net/eric/notarius/internal/modules/dnd"
	itemcodec "gitea.maximumdirect.net/eric/notarius/internal/modules/dnd/codec/itemregistry"
	itemidentity "gitea.maximumdirect.net/eric/notarius/internal/modules/dnd/items/identity"
)

func itemRegistryReferences(t *testing.T) contracts.ReferenceSet {
	t.Helper()
	content, err := itemcodec.New().Encode(dnd.ItemRegistry{Items: []dnd.Item{{ID: itemidentity.DeriveID("Torch"), Name: "Torch", SourceRefs: testSourceRefs()}}})
	if err != nil {
		t.Fatal(err)
	}
	return contracts.ReferenceSet{Slots: map[string]contracts.ResolvedReferenceSlot{ItemRegistryReferenceSlot: {Slot: contracts.ReferenceSlot{Name: ItemRegistryReferenceSlot}, Items: []contracts.ReferenceItem{{SlotName: ItemRegistryReferenceSlot, Content: content, MediaType: "application/json", ArtifactKind: dnd.ItemRegistryKind}}}}}
}

func emptyItemRegistryReferences(t *testing.T) contracts.ReferenceSet {
	t.Helper()
	content, err := itemcodec.New().Encode(dnd.ItemRegistry{Items: []dnd.Item{}})
	if err != nil {
		t.Fatal(err)
	}
	return contracts.ReferenceSet{Slots: map[string]contracts.ResolvedReferenceSlot{ItemRegistryReferenceSlot: {Slot: contracts.ReferenceSlot{Name: ItemRegistryReferenceSlot}, Items: []contracts.ReferenceItem{{SlotName: ItemRegistryReferenceSlot, Content: content, MediaType: "application/json", ArtifactKind: dnd.ItemRegistryKind}}}}}
}

func testSourceRefs() []source.SourceRef {
	return []source.SourceRef{{SourceID: "session-alpha", StartUnitID: 1, EndUnitID: 1}}
}

func TestModuleSpecDeclaresRequiredRegistry(t *testing.T) {
	spec := ModuleSpec()
	if spec.CorrectionProtocol != contracts.CorrectionProtocolSingleResponseV1 {
		t.Fatalf("correction protocol = %q, want %q", spec.CorrectionProtocol, contracts.CorrectionProtocolSingleResponseV1)
	}
	var slot contracts.ReferenceSlot
	for _, candidate := range spec.ReferenceSlots {
		if candidate.Name == ItemRegistryReferenceSlot {
			slot = candidate
		}
	}
	if !slot.Required || !reflect.DeepEqual(slot.AcceptedArtifactKinds, []contracts.ArtifactKind{dnd.ItemRegistryKind}) || slot.MaxBytes != ItemRegistryMaxBytes {
		t.Fatalf("registry slot = %#v", slot)
	}
	registry := pipeline.NewExtractorRegistry()
	if err := Register(registry); err != nil {
		t.Fatal(err)
	}
}
