package com.correx.core.validation.transition

import com.correx.core.transitions.graph.TransitionEdge
import com.correx.core.transitions.resolution.TransitionOrdering
import com.correx.core.validation.model.ValidationContext
import com.correx.core.validation.model.ValidationIssue
import com.correx.core.validation.model.ValidationLocation
import com.correx.core.validation.model.ValidationSection
import com.correx.core.validation.model.ValidationSeverity
import com.correx.core.validation.pipeline.Validator

class TransitionValidator(
    private val ordering: Comparator<TransitionEdge> = TransitionOrdering.comparator
) : Validator {

    override suspend fun validate(context: ValidationContext): ValidationSection {

        val graph = context.graph
        val issues = mutableListOf<ValidationIssue>()

        // group transitions by source node
        val grouped = graph.transitions.groupBy { it.from }

        // 1. endpoint integrity
        graph.transitions.forEach { edge ->
            if (edge.from !in graph.stages) {
                issues += ValidationIssue(
                    code = "TRANSITION_INVALID_FROM",
                    message = "Transition references missing 'from' stage",
                    severity = ValidationSeverity.ERROR,
                    location = ValidationLocation.Graph(
                        transitionId = edge.id
                    )
                )
            }

            if (edge.to !in graph.stages) {
                issues += ValidationIssue(
                    code = "TRANSITION_INVALID_TO",
                    message = "Transition references missing 'to' stage",
                    severity = ValidationSeverity.ERROR,
                    location = ValidationLocation.Graph(
                        transitionId = edge.id
                    )
                )
            }
        }

        // 2. deterministic ordering check per node
        grouped.forEach { (from, edges) ->

            val sorted = edges.sortedWith(ordering)

            // detect duplicate ordering signatures (ambiguity risk)
            val signatures = sorted.map { it.to }.toSet()

            if (signatures.size != sorted.size) {
                issues += ValidationIssue(
                    code = "TRANSITION_NON_DETERMINISTIC_ORDER",
                    message = "Non-deterministic ordering detected for node $from",
                    severity = ValidationSeverity.WARNING,
                    location = ValidationLocation.Graph(stageId = from)
                )
            }
        }

        return ValidationSection(
            name = "transition",
            issues = issues
        )
    }
}
