package contracts

import (
	"context"

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

// ExtractArtifact carries a typed per-chunk value with framework provenance.
type ExtractArtifact[T any] struct {
	LaneID       string
	ExtractorKey string
	SourceID     string
	ChunkID      string
	ChunkIndex   int
	ChunkRef     source.SourceRef
	Value        T
}

// MergeArtifact carries a typed merged value with framework provenance.
type MergeArtifact[T any] struct {
	LaneID    string
	MergerKey string
	SourceID  string
	Value     T
}

// NormalizeArtifact carries a typed normalized value with framework provenance.
type NormalizeArtifact[T any] struct {
	LaneID        string
	NormalizerKey string
	SourceID      string
	Value         T
}

type TypedExtractionRequest struct {
	Source                         *source.SourceDocument
	Chunk                          *source.Chunk
	AmbientContext                 map[string]any
	SourceInput                    LLMInputMaterial
	SessionID                      string
	References                     ReferenceSet
	LLMProfile                     string
	StructuredOutputRepairAttempts *int
	Correction                     *SemanticCorrection
	Metadata                       map[string]any
}

type TypedExtractionResult[T any] struct {
	Value          T
	Diagnostics    []ProducerDiagnostic
	ModelCandidate *ModelCandidate
}

type Extractor[T any] interface {
	Key() string
	ReferenceSlots() []ReferenceSlot
	Extract(context.Context, TypedExtractionRequest) (TypedExtractionResult[T], error)
}

type TypedMergeRequest[T any] struct {
	Source                         *source.SourceDocument
	LaneID                         string
	ExtractOutputs                 []ExtractArtifact[T]
	SourceInput                    LLMInputMaterial
	SessionID                      string
	References                     ReferenceSet
	LLMProfile                     string
	StructuredOutputRepairAttempts *int
	Correction                     *SemanticCorrection
	Metadata                       map[string]any
}

type TypedMergeResult[T any] struct {
	Value          T
	Diagnostics    []ProducerDiagnostic
	ModelCandidate *ModelCandidate
}

type Merger[T any] interface {
	Key() string
	Merge(context.Context, TypedMergeRequest[T]) (TypedMergeResult[T], error)
}

type TypedNormalizeRequest[T any] struct {
	Source                         *source.SourceDocument
	LaneID                         string
	MergeOutput                    MergeArtifact[T]
	SourceInput                    LLMInputMaterial
	SessionID                      string
	References                     ReferenceSet
	LLMProfile                     string
	StructuredOutputRepairAttempts *int
	Correction                     *SemanticCorrection
	Metadata                       map[string]any
}

type TypedNormalizeResult[T any] struct {
	Value          T
	Diagnostics    []ProducerDiagnostic
	Retry          *NormalizeRetry
	ModelCandidate *ModelCandidate
}

// Normalize retry limits bound module-provided control and diagnostic text
// before the framework consumes or records it.
const (
	MaxNormalizeRetryReasonCodeBytes         = 128
	MaxNormalizeRetryMessageBytes            = 4096
	MaxNormalizeRetryCorrectionGuidanceBytes = 4096
)

// NormalizeRetry asks the framework to retry normalization while retaining a
// safe candidate for acceptance if the retry budget is exhausted.
type NormalizeRetry struct {
	ReasonCode          string
	Message             string
	CorrectionGuidance  string
	FallbackDiagnostics []ProducerDiagnostic
}

type Normalizer[T any] interface {
	Key() string
	ReferenceSlots() []ReferenceSlot
	Normalize(context.Context, TypedNormalizeRequest[T]) (TypedNormalizeResult[T], error)
}

type TypedValidationRequest[T any] struct {
	Stage                          string
	LaneID                         string
	ModuleKey                      string
	Source                         *source.SourceDocument
	SourceID                       string
	SourceInput                    LLMInputMaterial
	SessionID                      string
	References                     ReferenceSet
	LLMProfile                     string
	StructuredOutputRepairAttempts *int
	Metadata                       map[string]any
	Chunk                          *source.Chunk
	Chunks                         []source.Chunk
	Ref                            source.SourceRef
	Value                          T
}

type TypedValidator[T any] interface {
	Name() string
	ExecutionClass() ExecutionClass
	Validate(context.Context, TypedValidationRequest[T]) (ValidationResult, error)
}

type ChunkValidationRequest struct {
	ModuleKey                      string
	Source                         *source.SourceDocument
	SourceID                       string
	SourceInput                    LLMInputMaterial
	SessionID                      string
	References                     ReferenceSet
	LLMProfile                     string
	StructuredOutputRepairAttempts *int
	Metadata                       map[string]any
	Chunks                         []source.Chunk
}

type ChunkValidator interface {
	Name() string
	ExecutionClass() ExecutionClass
	Validate(context.Context, ChunkValidationRequest) (ValidationResult, error)
}

type SerializedValidationRequest struct {
	Stage                          string
	LaneID                         string
	ModuleKey                      string
	Source                         *source.SourceDocument
	SourceID                       string
	SourceInput                    LLMInputMaterial
	SessionID                      string
	References                     ReferenceSet
	LLMProfile                     string
	StructuredOutputRepairAttempts *int
	Metadata                       map[string]any
	Chunk                          *source.Chunk
	Chunks                         []source.Chunk
	Schema                         ArtifactSchema
	MediaType                      string
	Content                        []byte
}

type SerializedValidator interface {
	Name() string
	ExecutionClass() ExecutionClass
	Validate(context.Context, SerializedValidationRequest) (ValidationResult, error)
}
