package pipeline

import (
	"context"
	"testing"

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

type retryingNotesNormalizer struct {
	warnings []contracts.Warning
	retry    *contracts.NormalizeRetry
}

func (retryingNotesNormalizer) Key() string                               { return "test/retry-normalize" }
func (retryingNotesNormalizer) ReferenceSlots() []contracts.ReferenceSlot { return nil }
func (n retryingNotesNormalizer) Normalize(_ context.Context, req contracts.TypedNormalizeRequest[codecNotes]) (contracts.TypedNormalizeResult[codecNotes], error) {
	return contracts.TypedNormalizeResult[codecNotes]{Value: req.MergeOutput.Value, Warnings: n.warnings, Retry: n.retry}, nil
}

func TestNormalizerRegistryErasureClonesRetryDirective(t *testing.T) {
	warnings := []contracts.Warning{{Scope: "attempt", ReasonCode: "ordinary", Message: "ordinary warning"}}
	retry := &contracts.NormalizeRetry{
		ReasonCode:       "retryable",
		Message:          "safe fallback available",
		FallbackWarnings: []contracts.Warning{{Scope: "fallback", ReasonCode: "omitted", Message: "fallback warning"}},
	}
	registry := NewNormalizerRegistry()
	if err := RegisterNormalizer(registry, ModuleSpec{Key: "test/retry-normalize", Stage: StageNormalize, ExecutionClass: contracts.ExecutionClassDeterministic, ArtifactKind: "test/notes"}, func() (contracts.Normalizer[codecNotes], error) {
		return retryingNotesNormalizer{warnings: warnings, retry: retry}, nil
	}); err != nil {
		t.Fatalf("RegisterNormalizer() error = %v", err)
	}
	entry, ok := registry.typedEntry("test/retry-normalize", "test/notes")
	if !ok {
		t.Fatal("typed normalizer entry missing")
	}
	implementation, err := entry.builder(BuildRequest{})
	if err != nil {
		t.Fatalf("builder() error = %v", err)
	}
	result, err := entry.normalize(context.Background(), implementation, contracts.TypedNormalizeRequest[any]{MergeOutput: contracts.MergeArtifact[any]{Value: codecNotes{Items: []string{"safe"}}}})
	if err != nil {
		t.Fatalf("normalize() error = %v", err)
	}
	warnings[0].Message = "mutated"
	retry.Message = "mutated"
	retry.FallbackWarnings[0].Message = "mutated"
	if result.Retry == nil || result.Warnings[0].Message != "ordinary warning" || result.Retry.Message != "safe fallback available" || result.Retry.FallbackWarnings[0].Message != "fallback warning" {
		t.Fatalf("erased retry result = %#v, want independent warning data", result)
	}
}
