package de.hoennig.werkator.commands

import de.hoennig.werkator.build.BuildResult
import de.hoennig.werkator.repo.RepoRegistry
import de.hoennig.werkator.server.UiFormats
import org.springframework.stereotype.Component
import picocli.CommandLine.Command
import picocli.CommandLine.ExitCode
import picocli.CommandLine.Mixin
import picocli.CommandLine.Option
import java.util.concurrent.Callable

/**
 * Reads the result repository directly, so it also works (read-only) while a server
 * instance is running against the same repository.
 */
@Component
@Command(
    name = "status",
    description = ["Print the latest build per branch"],
    mixinStandardHelpOptions = true,
)
class StatusCommand(
    private val registry: RepoRegistry,
) : Callable<Int> {
    @Option(names = ["--history"], description = ["Print all recorded builds, not only the latest per branch"])
    var history: Boolean = false

    @Mixin
    var repoOption = RepoOption()

    override fun call(): Int {
        val repository =
            try {
                repoOption.select(registry).results
            } catch (e: IllegalArgumentException) {
                System.err.println("error: ${e.message}")
                return ExitCode.USAGE
            }
        val results = if (history) repository.history() else repository.latestPerName()
        if (results.isEmpty()) {
            println("(no builds recorded)")
        } else {
            printTable(results)
        }
        return ExitCode.OK
    }

    private fun printTable(results: List<BuildResult>) {
        val header = listOf("BRANCH", "STATUS", "COMMIT", "TIME", "DURATION")
        val rows =
            results.map {
                listOf(
                    it.name,
                    it.status.name.lowercase(),
                    it.commit.take(12),
                    UiFormats.timestamp(it.startedAt),
                    UiFormats.duration(it.duration),
                )
            }
        val widths = header.indices.map { column -> (rows + listOf(header)).maxOf { row -> row[column].length } }
        for (row in listOf(header) + rows) {
            println(row.mapIndexed { column, cell -> cell.padEnd(widths[column]) }.joinToString("  ").trimEnd())
        }
    }
}
