package noop

import (
	"context"

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

type TypedNormalizer[T any] struct{}

func NewTyped[T any]() *TypedNormalizer[T] { return &TypedNormalizer[T]{} }

func (n *TypedNormalizer[T]) Key() string                               { return Key }
func (n *TypedNormalizer[T]) ReferenceSlots() []contracts.ReferenceSlot { return nil }

func (n *TypedNormalizer[T]) Normalize(ctx context.Context, req contracts.TypedNormalizeRequest[T]) (contracts.TypedNormalizeResult[T], error) {
	if n == nil {
		return contracts.TypedNormalizeResult[T]{}, normalizerErrorf("normalizer must not be nil")
	}
	if ctx == nil {
		return contracts.TypedNormalizeResult[T]{}, normalizerErrorf("context must not be nil")
	}
	if err := ctx.Err(); err != nil {
		return contracts.TypedNormalizeResult[T]{}, normalizerErrorf("context error before normalize: %w", err)
	}
	return contracts.TypedNormalizeResult[T]{Value: req.MergeOutput.Value}, nil
}

func TypedModuleSpec(kind contracts.ArtifactKind) pipeline.ModuleSpec {
	spec := ModuleSpec()
	spec.ArtifactKind = kind
	return spec
}

func RegisterTyped[T any](registry *pipeline.NormalizerRegistry, kind contracts.ArtifactKind) error {
	validateOptions := func(options map[string]any) error { return pipeline.RejectUnknownOptions(options) }
	return pipeline.RegisterNormalizerBuilder(registry, TypedModuleSpec(kind), validateOptions, func(request pipeline.BuildRequest) (contracts.Normalizer[T], error) {
		if err := pipeline.RejectUnknownOptions(request.Options); err != nil {
			return nil, err
		}
		return NewTyped[T](), nil
	})
}
