package com.correx.core.tasks

import com.correx.core.events.types.ProjectId
import com.correx.core.events.types.TaskId
import com.correx.core.events.types.TaskLinkType
import com.correx.core.events.types.TaskTargetKind
import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.Assertions.assertFalse
import org.junit.jupiter.api.Assertions.assertTrue
import org.junit.jupiter.api.Test

class TaskGraphTest {

    private fun task(id: String, status: TaskStatus = TaskStatus.TODO, links: List<TaskLink> = emptyList()) =
        Task(TaskId(id), TaskState(status = status, key = id, projectId = ProjectId("p"), title = id, links = links))

    private fun dependsOn(target: String) = TaskLink(target, TaskLinkType.DEPENDS_ON, TaskTargetKind.TASK)
    private fun blocks(target: String) = TaskLink(target, TaskLinkType.BLOCKS, TaskTargetKind.TASK)

    @Test
    fun `an unfinished depends_on target blocks the task`() {
        val a = task("p-1", links = listOf(dependsOn("p-2")))
        val b = task("p-2", status = TaskStatus.IN_PROGRESS)
        val board = listOf(a, b)

        assertEquals(listOf("p-2"), TaskGraph.unmetBlockers(a, board).map { it.taskId.value })
        assertFalse(TaskGraph.isReady(a, board))
    }

    @Test
    fun `a finished dependency no longer blocks`() {
        val a = task("p-1", links = listOf(dependsOn("p-2")))
        val done = task("p-2", status = TaskStatus.DONE)
        val board = listOf(a, done)

        assertTrue(TaskGraph.unmetBlockers(a, board).isEmpty())
        assertTrue(TaskGraph.isReady(a, board))
    }

    @Test
    fun `an inbound BLOCKS edge blocks the target`() {
        val a = task("p-1")
        val blocker = task("p-2", status = TaskStatus.IN_PROGRESS, links = listOf(blocks("p-1")))
        val board = listOf(a, blocker)

        assertEquals(listOf("p-2"), TaskGraph.unmetBlockers(a, board).map { it.taskId.value })
    }

    @Test
    fun `ready lists only unblocked TODO tasks`() {
        val a = task("p-1", links = listOf(dependsOn("p-2"))) // blocked
        val b = task("p-2", status = TaskStatus.IN_PROGRESS)  // not TODO
        val c = task("p-3")                                   // unblocked TODO → ready

        assertEquals(listOf("p-3"), TaskGraph.ready(listOf(a, b, c)).map { it.taskId.value })
    }

    @Test
    fun `blocking lists what completing a task unblocks`() {
        val dependent = task("p-1", links = listOf(dependsOn("p-2")))
        val target = task("p-2")
        val board = listOf(dependent, target)

        assertEquals(listOf("p-1"), TaskGraph.blocking(target, board).map { it.taskId.value })
    }
}
