package com.correx.infrastructure.workflow

import org.junit.jupiter.api.Test
import org.junit.jupiter.api.assertThrows
import java.nio.file.Files
import kotlin.io.path.writeText
import kotlin.test.assertEquals

class TomlWorkflowLoaderTest {

    private val loader = TomlWorkflowLoader()

    private val validToml = """
        id = "healthcheck"
        start = "collect"

        [[stages]]
        id = "collect"
        prompt = "prompts/collect.md"
        produces = [{ name = "system_stats", kind = "file_written" }]
        allowed_tools = ["ShellTool"]
        token_budget = 2048
        max_retries = 2

        [[stages]]
        id = "report"
        prompt = "prompts/report.md"
        needs = ["system_stats"]
        produces = [{ name = "report", kind = "file_written" }]
        token_budget = 2048

        [[transitions]]
        id = "collect-to-report"
        from = "collect"
        to = "report"
        condition_type = "artifact_present"
        condition_artifact_id = "system_stats"

        [[transitions]]
        id = "report-to-done"
        from = "report"
        to = "done"
        condition_type = "always_true"
    """.trimIndent()

    @Test
    fun `valid toml produces correct WorkflowGraph`() {
        val path = Files.createTempFile("workflow", ".toml").also { it.writeText(validToml) }
        val graph = loader.load(path)

        assertEquals("collect", graph.start.value)
        assertEquals(2, graph.stages.size)
        assertEquals(2, graph.transitions.size)

        val collectStage = graph.stages[graph.start]!!
        assertEquals(setOf("system_stats"), collectStage.produces.map { it.name.value }.toSet())
        assertEquals("prompts/collect.md", collectStage.metadata["prompt"])

        val reportStage = graph.stages.values.first { it.produces.any { a -> a.name.value == "report" } }
        assertEquals(setOf("system_stats"), reportStage.needs.map { it.value }.toSet())
    }

    @Test
    fun `missing stage reference throws WorkflowValidationException`() {
        val bad = validToml.replace("from = \"collect\"", "from = \"nonexistent\"")
        val path = Files.createTempFile("workflow", ".toml").also { it.writeText(bad) }
        assertThrows<WorkflowValidationException> { loader.load(path) }
    }

    @Test
    fun `duplicate transition ids throw WorkflowValidationException`() {
        val bad = validToml.replace("id = \"report-to-done\"", "id = \"collect-to-report\"")
        val path = Files.createTempFile("workflow", ".toml").also { it.writeText(bad) }
        assertThrows<WorkflowValidationException> { loader.load(path) }
    }

    @Test
    fun `unknown start stage throws WorkflowValidationException`() {
        val bad = validToml.replace("start = \"collect\"", "start = \"missing\"")
        val path = Files.createTempFile("workflow", ".toml").also { it.writeText(bad) }
        assertThrows<WorkflowValidationException> { loader.load(path) }
    }

    @Test
    fun `unsatisfied needs throws WorkflowValidationException`() {
        val bad = validToml.replace(
            "needs = [\"system_stats\"]",
            "needs = [\"nonexistent_artifact\"]",
        )
        val path = Files.createTempFile("workflow", ".toml").also { it.writeText(bad) }
        assertThrows<WorkflowValidationException> { loader.load(path) }
    }

    @Test
    fun `unknown artifact kind throws error`() {
        val bad = validToml.replace("kind = \"file_written\"", "kind = \"unknown_kind\"")
        val path = Files.createTempFile("workflow", ".toml").also { it.writeText(bad) }
        assertThrows<IllegalStateException> { loader.load(path) }
    }
}
