package dev.rnett.gradle.mcp.repl

import kotlinx.serialization.Serializable

@Serializable
data class KotlinCompilerPluginOption(
    val pluginId: String,
    val optionName: String,
    val value: String
)

@Serializable
data class ReplConfig(
    val classpath: List<String> = emptyList(),
    val pluginsClasspath: List<String> = emptyList(),
    val compilerPluginOptions: List<KotlinCompilerPluginOption> = emptyList(),
    val compilerArgs: List<String> = emptyList(),
    val env: Map<String, String> = emptyMap()
)

@Serializable
data class ReplRequest(
    val code: String
)

@Serializable
sealed class ReplResponse {

    companion object {
        const val RPC_PREFIX = "[gradle-mcp-repl-rpc]"
    }

    @Serializable
    sealed class Output : ReplResponse() {
        abstract val data: String

        @Serializable
        data class Stdout(override val data: String) : Output()

        @Serializable
        data class Stderr(override val data: String) : Output()
    }

    @Serializable
    data class Logging(
        val loggerName: String,
        val level: Level,
        val message: String
    ) : ReplResponse() {
        @Serializable
        enum class Level {
            DEBUG, INFO, WARN, ERROR;
        }
    }

    @Serializable
    data class Data(
        val value: String,
        val mime: String = "text/plain",
        val meta: Map<String, String> = emptyMap()
    ) : ReplResponse()

    @Serializable
    sealed class Result : ReplResponse() {
        @Serializable
        data class Success(
            val data: Data
        ) : Result()

        @Serializable
        data class CompilationError(val message: String, val location: String?) : Result()

        @Serializable
        data class RuntimeError(val message: String, val stackTrace: String? = null) : Result()

        @Serializable
        data class InternalError(val message: String, val stackTrace: String? = null) : Result()
    }
}
