package identity

import (
	"context"
	"strings"
	"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"
	domainidentity "gitea.maximumdirect.net/eric/notarius/internal/modules/dnd/items/identity"
)

func TestValidatorRejectsInvalidAndDuplicateItemIdentity(t *testing.T) {
	value := dnd.ItemRegistry{Items: []dnd.Item{
		{ID: "wrong", Name: "Rope", SourceRefs: []source.SourceRef{{SourceID: "session", StartUnitID: 1, EndUnitID: 1}}},
		{ID: domainidentity.DeriveID("rope"), Name: "rope", SourceRefs: []source.SourceRef{{SourceID: "session", StartUnitID: 2, EndUnitID: 2}}},
	}}
	result, err := New(Options{}).Validate(context.Background(), contracts.TypedValidationRequest[dnd.ItemRegistry]{Value: value})
	if err != nil || result.Approved || result.ReasonCode != ReasonCode || !strings.Contains(result.Message, "invalid_id") || !strings.Contains(result.Message, "duplicate_canonical_identity") {
		t.Fatalf("Validate() = %#v, %v; want identity rejection", result, err)
	}
	if !strings.Contains(result.CorrectionGuidance, "duplicate-group proposals") || !strings.Contains(result.CorrectionGuidance, "Rope") || strings.Contains(result.CorrectionGuidance, "wrong") || strings.Contains(result.CorrectionGuidance, "items[") {
		t.Fatalf("CorrectionGuidance = %q, want contextual proposal guidance without IDs or operator paths", result.CorrectionGuidance)
	}
}

func TestValidatorRegistersPolicy(t *testing.T) {
	registry := pipeline.NewValidatorRegistry()
	if err := Register(registry); err != nil {
		t.Fatal(err)
	}
	if got, ok := registry.Spec(Key); !ok || got != Spec() || got.ExecutionClass != contracts.ExecutionClassDeterministic {
		t.Fatalf("registered spec = %#v, present = %t", got, ok)
	}
	if got := New(Options{}).CheckpointFingerprints(); len(got) != 2 || got[0].Value != domainidentity.Policy || got[1].Name != "correction_policy" || got[1].Value != correctionPolicy {
		t.Fatalf("fingerprints = %#v", got)
	}
	if _, err := DecodeOptions(map[string]any{"unexpected": true}); err == nil {
		t.Fatal("DecodeOptions accepted unknown options")
	}
}
