package com.correx.apps.cli.commands

import com.correx.apps.cli.CorrexCli
import com.correx.apps.cli.DEFAULT_PORT
import com.github.ajalt.clikt.core.CliktCommand
import com.github.ajalt.clikt.parameters.options.default
import com.github.ajalt.clikt.parameters.options.option
import io.ktor.client.HttpClient
import io.ktor.client.call.body
import io.ktor.client.engine.cio.CIO
import io.ktor.client.plugins.contentnegotiation.ContentNegotiation
import io.ktor.client.request.get
import io.ktor.client.statement.bodyAsText
import io.ktor.serialization.kotlinx.json.json
import kotlinx.coroutines.runBlocking
import kotlinx.serialization.Serializable
import kotlinx.serialization.json.Json

@Serializable
data class HealthSubjectReportDto(
    val subject: String,
    val status: String,
    val metric: String,
    val observedValue: Long = 0,
    val detail: String = "",
    val since: String = "",
)

@Serializable
data class HealthReportDto(
    val overall: String = "HEALTHY",
    val subjects: List<HealthSubjectReportDto> = emptyList(),
    val checkedAt: String = "",
)

fun renderHealth(report: HealthReportDto): String {
    val lines = mutableListOf<String>()
    lines += "Overall:   ${report.overall}"
    if (report.checkedAt.isNotEmpty()) lines += "Checked:   ${report.checkedAt}"
    lines += ""
    if (report.subjects.isEmpty()) {
        lines += "No health checks recorded yet."
        return lines.joinToString("\n")
    }
    for (s in report.subjects) {
        lines += "%-14s %-9s %s".format(s.subject, s.status, s.detail)
        if (s.since.isNotEmpty()) lines += "               since ${s.since}"
    }
    return lines.joinToString("\n")
}

class HealthCommand : CliktCommand(name = "health") {
    private val host by option("--host").default("localhost")
    private val port by option("--port").default("$DEFAULT_PORT")

    private val healthJson = Json { ignoreUnknownKeys = true }

    override fun run(): Unit = runBlocking {
        val portInt = port.toIntOrNull() ?: DEFAULT_PORT
        val outputJson = (currentContext.findRoot().command as? CorrexCli)?.json ?: false
        val url = "http://$host:$portInt/health/checks"

        val client = HttpClient(CIO) {
            install(ContentNegotiation) { json(healthJson) }
        }

        runCatching {
            if (outputJson) {
                println(client.get(url).bodyAsText())
            } else {
                println(renderHealth(client.get(url).body()))
            }
        }.onFailure { e ->
            System.err.println("Error fetching health: ${e.message}")
        }

        client.close()
    }
}
