package com.correx.core.config

import org.junit.jupiter.api.Test
import kotlin.test.assertEquals
import kotlin.test.assertFalse
import kotlin.test.assertTrue

class EditableConfigTest {

    @Test
    fun `applies an int patch`() {
        val out = EditableConfig.apply(CorrexConfig(), mapOf("tui.session_list_limit" to "12")).getOrThrow()
        assertEquals(12, out.tui.sessionListLimit)
    }

    @Test
    fun `applies a bool patch`() {
        val out = EditableConfig.apply(CorrexConfig(), mapOf("project.enabled" to "true")).getOrThrow()
        assertTrue(out.project.enabled)
    }

    @Test
    fun `applies a double and long patch`() {
        val out = EditableConfig.apply(
            CorrexConfig(),
            mapOf("router.generation.temperature" to "0.25", "orchestration.stage_timeout_ms" to "90000"),
        ).getOrThrow()
        assertEquals(0.25, out.talkie.generation.temperature)
        assertEquals(90_000L, out.orchestration.stageTimeoutMs)
    }

    @Test
    fun `applies an enum patch and rejects an out-of-range enum`() {
        val out = EditableConfig.apply(CorrexConfig(), mapOf("tui.theme" to "light")).getOrThrow()
        assertEquals("light", out.tui.theme)
        assertTrue(EditableConfig.apply(CorrexConfig(), mapOf("tui.theme" to "neon")).isFailure)
    }

    @Test
    fun `rejects unknown key`() {
        assertTrue(EditableConfig.apply(CorrexConfig(), mapOf("nope.field" to "1")).isFailure)
    }

    @Test
    fun `rejects security key and excludes it from the registry`() {
        assertTrue(EditableConfig.apply(CorrexConfig(), mapOf("tools.sandbox_root" to "/etc")).isFailure)
        assertTrue(EditableConfig.fields.none { it.key == "tools.sandbox_root" })
        assertTrue(EditableConfig.fields.none { it.key == "tools.shell_allowed_executables" })
    }

    @Test
    fun `rejects non-numeric int`() {
        assertTrue(EditableConfig.apply(CorrexConfig(), mapOf("tui.session_list_limit" to "abc")).isFailure)
    }

    @Test
    fun `marks server fields restart-required`() {
        assertTrue("server.port" in EditableConfig.restartRequiredKeys)
        assertTrue("server.host" in EditableConfig.restartRequiredKeys)
        assertFalse("tui.theme" in EditableConfig.restartRequiredKeys)
    }

    @Test
    fun `getString reflects current value for every field`() {
        val cfg = CorrexConfig()
        // Every field renders without throwing and a patch with that rendered value is a no-op.
        EditableConfig.fields.forEach { f ->
            val rendered = f.getString(cfg)
            val out = EditableConfig.apply(cfg, mapOf(f.key to rendered)).getOrThrow()
            assertEquals(rendered, f.getString(out), "round-trip via getString failed for ${f.key}")
        }
    }
}
