package artifacts

import (
	"strings"
	"time"
)

type ArtifactLaneManifest struct {
	StepID     string         `json:"step_id,omitempty"`
	ID         string         `json:"id"`
	Extractor  string         `json:"extractor"`
	Merger     string         `json:"merger"`
	Normalizer string         `json:"normalizer"`
	Metadata   map[string]any `json:"metadata,omitempty"`
}

type ValidatorChainManifest struct {
	Stage      string              `json:"stage"`
	LaneID     string              `json:"lane_id,omitempty"`
	ModuleKey  string              `json:"module_key"`
	Validators []ValidatorManifest `json:"validators"`
}

type ValidatorManifest struct {
	Key            string `json:"key"`
	ExecutionClass string `json:"execution_class"`
}

type LLMProfileManifest struct {
	ID              string `json:"id"`
	Provider        string `json:"provider,omitempty"`
	Model           string `json:"model,omitempty"`
	BackendID       string `json:"backend_id,omitempty"`
	ReasoningEffort string `json:"reasoning_effort,omitempty"`
}

// Normalized returns the canonical representation used for manifest identity
// and publication.
func (profile LLMProfileManifest) Normalized() LLMProfileManifest {
	profile.ID = strings.TrimSpace(profile.ID)
	profile.Provider = strings.TrimSpace(profile.Provider)
	profile.Model = strings.TrimSpace(profile.Model)
	profile.BackendID = strings.TrimSpace(profile.BackendID)
	profile.ReasoningEffort = strings.TrimSpace(profile.ReasoningEffort)
	return profile
}

// IdentityKey returns an opaque, deterministic key for the effective profile.
func (profile LLMProfileManifest) IdentityKey() string {
	profile = profile.Normalized()
	return profile.ID + "\x00" +
		profile.Provider + "\x00" +
		profile.Model + "\x00" +
		profile.BackendID + "\x00" +
		profile.ReasoningEffort
}

type ReferenceProvenance struct {
	Stage            string `json:"stage,omitempty"`
	StepID           string `json:"step_id,omitempty"`
	LaneID           string `json:"lane_id,omitempty"`
	SlotName         string `json:"slot_name"`
	OriginType       string `json:"origin_type"`
	OriginURI        string `json:"origin_uri,omitempty"`
	Digest           string `json:"digest,omitempty"`
	MediaType        string `json:"media_type,omitempty"`
	SizeBytes        int64  `json:"size_bytes,omitempty"`
	BindingSource    string `json:"binding_source,omitempty"`
	ArtifactKind     string `json:"artifact_kind,omitempty"`
	SchemaID         string `json:"schema_id,omitempty"`
	SchemaName       string `json:"schema_name,omitempty"`
	SchemaVersion    string `json:"schema_version,omitempty"`
	SchemaDigest     string `json:"schema_digest,omitempty"`
	ProducerPipeline string `json:"producer_pipeline_id,omitempty"`
	ProducerStep     string `json:"producer_step_id,omitempty"`
	ProducerLane     string `json:"producer_lane_id,omitempty"`
	ProducerModule   string `json:"producer_module_key,omitempty"`
}

type OutputSchemaProvenance struct {
	ID      string `json:"id,omitempty"`
	Name    string `json:"name,omitempty"`
	Version string `json:"version,omitempty"`
}

type NormalizedOutputManifest struct {
	StepID    string                 `json:"step_id,omitempty"`
	LaneID    string                 `json:"lane_id"`
	ModuleKey string                 `json:"module_key,omitempty"`
	SourceID  string                 `json:"source_id,omitempty"`
	MediaType string                 `json:"media_type,omitempty"`
	Schema    OutputSchemaProvenance `json:"schema,omitempty"`
}

type RejectedOutputManifest struct {
	Stage                  string             `json:"stage"`
	StepID                 string             `json:"step_id,omitempty"`
	LaneID                 string             `json:"lane_id,omitempty"`
	ModuleKey              string             `json:"module_key,omitempty"`
	ChunkID                string             `json:"chunk_id,omitempty"`
	ChunkIndex             int                `json:"chunk_index,omitempty"`
	ValidatorName          string             `json:"validator_name,omitempty"`
	ReasonCode             string             `json:"reason_code,omitempty"`
	Message                string             `json:"message,omitempty"`
	AttemptCount           int                `json:"attempt_count,omitempty"`
	DiagnosticArtifactPath string             `json:"diagnostic_artifact_path,omitempty"`
	Validation             *ValidationSummary `json:"validation,omitempty"`
}

// ValidationSummary is the bounded, durable outcome of validating one
// producer result. It deliberately contains identities and stable codes, not
// model responses, corrective guidance, validator diagnostics, or payloads.
type ValidationSummary struct {
	Stage                string   `json:"stage,omitempty"`
	StepID               string   `json:"step_id,omitempty"`
	LaneID               string   `json:"lane_id,omitempty"`
	ModuleKey            string   `json:"module_key,omitempty"`
	ChunkID              string   `json:"chunk_id,omitempty"`
	ChunkIndex           int      `json:"chunk_index,omitempty"`
	Status               string   `json:"status"`
	RejectingValidators  []string `json:"rejecting_validators,omitempty"`
	ReasonCodes          []string `json:"reason_codes,omitempty"`
	IncompleteValidators []string `json:"incomplete_validators,omitempty"`
	ProducerAttemptCount int      `json:"producer_attempt_count"`
	TerminalAction       string   `json:"terminal_action"`
}

// CloneValidationSummary returns an independently owned durable summary.
func CloneValidationSummary(summary ValidationSummary) ValidationSummary {
	summary.RejectingValidators = append([]string(nil), summary.RejectingValidators...)
	summary.ReasonCodes = append([]string(nil), summary.ReasonCodes...)
	summary.IncompleteValidators = append([]string(nil), summary.IncompleteValidators...)
	return summary
}

type CheckpointDecisionManifest struct {
	Stage      string `json:"stage"`
	StepID     string `json:"step_id,omitempty"`
	LaneID     string `json:"lane_id,omitempty"`
	ModuleKey  string `json:"module_key,omitempty"`
	Category   string `json:"category"`
	ReasonCode string `json:"reason_code,omitempty"`
	Detail     string `json:"detail,omitempty"`
}

type ChunkPlanManifest struct {
	Mode                string                `json:"mode"`
	Action              string                `json:"action,omitempty"`
	SourceDigest        string                `json:"source_digest,omitempty"`
	PlanDigest          string                `json:"plan_digest,omitempty"`
	PlanSchemaVersion   string                `json:"plan_schema_version,omitempty"`
	RequestedModule     string                `json:"requested_module"`
	ProducerInputModule string                `json:"producer_input_module,omitempty"`
	ProducerModule      string                `json:"producer_module,omitempty"`
	ProducerLLMProfile  string                `json:"producer_llm_profile,omitempty"`
	ProducerReferences  []ReferenceProvenance `json:"producer_references,omitempty"`
	ProducerMetadata    map[string]any        `json:"producer_metadata,omitempty"`
	CreatedAt           *time.Time            `json:"created_at,omitempty"`
}

// ChunkPlanSummary is deliberately limited to cache and validation decisions.
// It must never contain plan units, source content, annotations, or model I/O.
type ChunkPlanSummary struct {
	Mode              string `json:"mode"`
	SourceDigest      string `json:"source_digest,omitempty"`
	CandidateDigest   string `json:"candidate_digest,omitempty"`
	RequestedModule   string `json:"requested_module"`
	LookupStatus      string `json:"lookup_status"`
	LookupReason      string `json:"lookup_reason,omitempty"`
	Action            string `json:"action,omitempty"`
	ValidationStatus  string `json:"validation_status"`
	PublicationStatus string `json:"publication_status"`
}

type RunManifest struct {
	RunID               string                       `json:"run_id,omitempty"`
	PipelineID          string                       `json:"pipeline_id,omitempty"`
	PipelineDigest      string                       `json:"pipeline_digest,omitempty"`
	InputModule         string                       `json:"input_module,omitempty"`
	Chunker             string                       `json:"chunker,omitempty"`
	ChunkPlan           *ChunkPlanManifest           `json:"chunk_plan,omitempty"`
	SourceDigests       []string                     `json:"source_digests,omitempty"`
	Extractors          []string                     `json:"extractors,omitempty"`
	Merger              string                       `json:"merger,omitempty"`
	Normalizer          string                       `json:"normalizer,omitempty"`
	OutputEncoder       string                       `json:"output_encoder,omitempty"`
	ModuleMetadata      map[string]map[string]any    `json:"module_metadata,omitempty"`
	ArtifactLanes       []ArtifactLaneManifest       `json:"artifact_lanes,omitempty"`
	ValidatorChains     []ValidatorChainManifest     `json:"validator_chains,omitempty"`
	References          []ReferenceProvenance        `json:"references,omitempty"`
	NormalizedOutputs   []NormalizedOutputManifest   `json:"normalized_outputs,omitempty"`
	RejectedOutputs     []RejectedOutputManifest     `json:"rejected_outputs,omitempty"`
	ValidationSummaries []ValidationSummary          `json:"validation_summaries,omitempty"`
	CheckpointDecisions []CheckpointDecisionManifest `json:"checkpoint_decisions,omitempty"`
	LLMProfiles         []LLMProfileManifest         `json:"llm_profiles,omitempty"`
	Metadata            map[string]any               `json:"metadata,omitempty"`
	SchemaVersion       string                       `json:"schema_version,omitempty"`
	ValidationStatus    string                       `json:"validation_status,omitempty"`
	StartedAt           *time.Time                   `json:"started_at,omitempty"`
	CompletedAt         *time.Time                   `json:"completed_at,omitempty"`
}
