package com.correx.core.tasks

/**
 * Renders the task board to Markdown — a *disposable projection* of the event log, grouped by
 * status. It is never a source of truth: regenerate it, don't hand-edit it. Pure and store-free
 * so it can render either [TaskService.list] or [TaskService.listAll] and be unit tested directly.
 */
object TaskMarkdown {

    // Active work first, terminal states last.
    private val ORDER = listOf(
        TaskStatus.IN_PROGRESS,
        TaskStatus.IN_REVIEW,
        TaskStatus.BLOCKED,
        TaskStatus.TODO,
        TaskStatus.DONE,
        TaskStatus.CANCELLED,
    )

    fun render(tasks: List<Task>): String = buildString {
        appendLine("# Tasks")
        appendLine()
        appendLine("_Generated from the correx event log — disposable; regenerate, don't edit._")
        appendLine()
        if (tasks.isEmpty()) {
            appendLine("_No tasks._")
            return@buildString
        }
        val byStatus = tasks.groupBy { it.state.status }
        for (status in ORDER) {
            val group = byStatus[status]?.sortedBy { it.taskId.value }.orEmpty()
            if (group.isEmpty()) continue
            appendLine("## ${heading(status)} (${group.size})")
            appendLine()
            group.forEach { appendLine(item(it)) }
            appendLine()
        }
    }.trimEnd() + "\n"

    private fun item(task: Task): String {
        val check = if (task.state.status == TaskStatus.DONE) "x" else " "
        val claim = task.state.claimant?.let { " _(@$it)_" }.orEmpty()
        return "- [$check] **${task.taskId.value}** ${task.state.title.orEmpty()}$claim".trimEnd()
    }

    private fun heading(status: TaskStatus): String = when (status) {
        TaskStatus.TODO -> "To do"
        TaskStatus.IN_PROGRESS -> "In progress"
        TaskStatus.IN_REVIEW -> "In review"
        TaskStatus.BLOCKED -> "Blocked"
        TaskStatus.DONE -> "Done"
        TaskStatus.CANCELLED -> "Cancelled"
    }
}
