package com.correx.core.validation.pipeline

import com.correx.core.validation.approval.ApprovalTrigger
import com.correx.core.validation.model.ValidationContext
import com.correx.core.validation.model.ValidationReport
import com.correx.core.validation.model.ValidationSection
import com.correx.core.validation.model.ValidationSeverity

private const val ARTIFACT_PAYLOAD_SECTION = "artifact_payload"

class ValidationPipeline(
    private val validators: List<Validator>,
    private val approvalTrigger: ApprovalTrigger? = null
) {

    suspend fun validate(context: ValidationContext): ValidationOutcome {
        val sections = mutableListOf<ValidationSection>()
        for (validator in validators) {
            val section = validator.validate(context)
            sections += section
            if (section.issues.any { it.severity == ValidationSeverity.ERROR }) {
                // Distinguish failure classes: a malformed/schema-invalid LLM artifact is
                // retryable (the model is nondeterministic — a fresh attempt usually succeeds,
                // up to the stage's max_retries; this is the invariant #7 "reject + retry"
                // contract). Structural/graph errors are not retryable — the graph must be fixed.
                val retryable = section.name == ARTIFACT_PAYLOAD_SECTION
                return ValidationOutcome.Rejected(ValidationReport(sections), retryable = retryable)
            }
        }
        val report = ValidationReport(sections)
        val approvalRequest = approvalTrigger?.evaluate(report)
        return if (approvalRequest != null) {
            ValidationOutcome.NeedsApproval(approvalRequest)
        } else {
            ValidationOutcome.Passed(report)
        }
    }
}
