package com.correx.core.validation.artifact

import com.correx.core.artifacts.kind.JsonSchema
import com.correx.core.artifacts.kind.JsonSchemaProperty
import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.Assertions.assertInstanceOf
import org.junit.jupiter.api.Test

class ArtifactExtractionPipelineTest {

    private val pipeline = ArtifactExtractionPipeline()
    private val fileWritten = JsonSchema(
        type = "object",
        properties = mapOf(
            "path" to JsonSchemaProperty(type = "string"),
            "content" to JsonSchemaProperty(type = "string"),
            "mode" to JsonSchemaProperty(type = "string", default = "0644"),
        ),
        required = listOf("path", "content"),
    )

    private fun resolved(raw: String) =
        assertInstanceOf(
            ArtifactExtractionPipeline.ExtractionResult.Resolved::class.java,
            pipeline.run(raw, fileWritten),
        )

    @Test
    fun `clean json passes through`() {
        val r = resolved("""{"path":"a.kt","content":"x"}""")
        assertEquals("a.kt", (r.canonicalJson["path"] as kotlinx.serialization.json.JsonPrimitive).content)
    }

    @Test
    fun `prose-wrapped json is rescued`() {
        resolved("""Sure! Here is the file:\n{"path":"a.kt","content":"x"} Let me know if you need changes.""")
    }

    @Test
    fun `code-fenced json is rescued`() {
        resolved("```json\n{\"path\":\"a.kt\",\"content\":\"x\"}\n```")
    }

    @Test
    fun `trailing comma is repaired`() {
        resolved("""{"path":"a.kt","content":"x",}""")
    }

    @Test
    fun `unquoted keys are repaired`() {
        resolved("""{path:"a.kt",content:"x"}""")
    }

    @Test
    fun `missing default is filled`() {
        val r = resolved("""{"path":"a.kt","content":"x"}""")
        assertEquals("0644", (r.canonicalJson["mode"] as kotlinx.serialization.json.JsonPrimitive).content)
    }

    @Test
    fun `schema-shaped but missing required is unresolved`() {
        assertInstanceOf(
            ArtifactExtractionPipeline.ExtractionResult.Unresolved::class.java,
            pipeline.run("""{"path":"a.kt"}""", fileWritten),
        )
    }

    @Test
    fun `pure prose with no json is unresolved`() {
        assertInstanceOf(
            ArtifactExtractionPipeline.ExtractionResult.Unresolved::class.java,
            pipeline.run("I could not complete this task.", fileWritten),
        )
    }
}
