import com.correx.core.validation.model.ValidationContext
import com.correx.core.validation.model.ValidationIssue
import com.correx.core.validation.model.ValidationSection
import com.correx.core.validation.model.ValidationSeverity
import com.correx.core.validation.pipeline.ValidationOutcome
import com.correx.core.validation.pipeline.ValidationPipeline
import com.correx.core.validation.pipeline.Validator
import com.correx.testing.fixtures.WorkflowFixtures
import kotlinx.coroutines.runBlocking
import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.Assertions.assertFalse
import org.junit.jupiter.api.Test

class ValidationPipelineShortCircuitTest {

    private val context = ValidationContext(WorkflowFixtures.simpleGraph())

    private fun errorValidator(name: String = "first") = Validator { _ ->
        ValidationSection(
            name = name,
            issues = listOf(ValidationIssue("ERR", "failure", ValidationSeverity.ERROR))
        )
    }

    @Test
    fun `pipeline stops after first validator with errors and report contains only that section`(): Unit = runBlocking {
        var secondCalled = false
        val trackingValidator = Validator { _ ->
            secondCalled = true
            ValidationSection(name = "second")
        }

        val pipeline = ValidationPipeline(listOf(errorValidator(), trackingValidator))
        val outcome = pipeline.validate(context) as ValidationOutcome.Rejected

        assertFalse(secondCalled, "second validator must not run after a rejection")
        assertEquals(1, outcome.report.sections.size)
        assertEquals("first", outcome.report.sections[0].name)
    }

    @Test
    fun `warnings do not short-circuit the pipeline`(): Unit = runBlocking {
        var secondCalled = false

        val warningValidator = Validator { _ ->
            ValidationSection(
                name = "first",
                issues = listOf(ValidationIssue("WARN", "warning", ValidationSeverity.WARNING))
            )
        }
        val trackingValidator = Validator { _ ->
            secondCalled = true
            ValidationSection(name = "second")
        }

        val pipeline = ValidationPipeline(listOf(warningValidator, trackingValidator))
        pipeline.validate(context)

        assert(secondCalled) { "warnings must not stop pipeline execution" }
    }
}
