package pipeline

import (
	"reflect"
	"strings"
	"testing"

	"gitea.maximumdirect.net/eric/notarius/internal/core/source"
	"gitea.maximumdirect.net/eric/notarius/internal/framework/contracts"
)

func TestArtifactEvidenceRegistryProjectsExactRegisteredTypesWithOwnedReferences(t *testing.T) {
	registry := NewArtifactEvidenceRegistry()
	input := codecNotes{Items: []string{"one"}}
	refs := []source.SourceRef{{SourceID: "source", StartUnitID: 2, EndUnitID: 2}}
	if err := RegisterArtifactEvidence(registry, "test/notes", func(codecNotes) []source.SourceRef { return refs }); err != nil {
		t.Fatalf("RegisterArtifactEvidence() error = %v, want nil", err)
	}
	if err := RegisterArtifactEvidence(registry, "test/score", func(codecScore) []source.SourceRef { return nil }); err != nil {
		t.Fatalf("RegisterArtifactEvidence() second kind error = %v, want nil", err)
	}
	if got, want := registry.RegisteredKinds(), []contracts.ArtifactKind{"test/notes", "test/score"}; !reflect.DeepEqual(got, want) {
		t.Fatalf("RegisteredKinds() = %#v, want %#v", got, want)
	}
	projected, err := registry.Project(" test/notes ", input)
	if err != nil {
		t.Fatalf("Project() error = %v, want nil", err)
	}
	projected[0].StartUnitID = 99
	if refs[0].StartUnitID != 2 {
		t.Fatal("Project() retained projector reference storage")
	}
	if _, err := registry.Project("test/notes", codecNotesAlias(input)); err == nil || !strings.Contains(err.Error(), "expected exact Go type") {
		t.Fatalf("Project() exact type error = %v, want exact type failure", err)
	}
}

func TestArtifactEvidenceRegistryRejectsInvalidRegistration(t *testing.T) {
	registry := NewArtifactEvidenceRegistry()
	if err := RegisterArtifactEvidence[codecNotes](nil, "test/notes", func(codecNotes) []source.SourceRef { return nil }); err == nil || !strings.Contains(err.Error(), "must not be nil") {
		t.Fatalf("nil registry error = %v, want failure", err)
	}
	if err := RegisterArtifactEvidence(registry, " ", func(codecNotes) []source.SourceRef { return nil }); err == nil || !strings.Contains(err.Error(), "must not be empty") {
		t.Fatalf("blank kind error = %v, want failure", err)
	}
	if err := RegisterArtifactEvidence(registry, "test/notes", ArtifactEvidenceProjector[codecNotes](nil)); err == nil || !strings.Contains(err.Error(), "must not be nil") {
		t.Fatalf("nil projector error = %v, want failure", err)
	}
	if err := RegisterArtifactEvidence(registry, "test/notes", func(codecNotes) []source.SourceRef { return nil }); err != nil {
		t.Fatal(err)
	}
	if err := RegisterArtifactEvidence(registry, "test/notes", func(codecNotes) []source.SourceRef { return nil }); err == nil || !strings.Contains(err.Error(), "already registered") {
		t.Fatalf("duplicate kind error = %v, want failure", err)
	}
}
