package com.correx.core.transitions.analysis.canonicalization

import com.correx.core.events.types.StageId
import com.correx.core.events.types.TransitionId
import com.correx.core.transitions.analysis.DetectedCycle
import com.correx.core.transitions.graph.TransitionEdge
import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.Test

class CycleCanonicalizerTest {

    private fun edge(id: String, from: String, to: String) = TransitionEdge(
        id = TransitionId(id),
        from = StageId(from),
        to = StageId(to),
        condition = { true }
    )

    @Test
    fun `same node set but different edges produce two entries`() {
        // A -> B -> A with edge t1, and A -> B -> A with edge t2 — different edges
        val cycleWithT1 = DetectedCycle(
            nodes = listOf(StageId("A"), StageId("B"), StageId("A")),
            edges = listOf(edge("t1", "A", "B"), edge("t1b", "B", "A"))
        )
        val cycleWithT2 = DetectedCycle(
            nodes = listOf(StageId("A"), StageId("B"), StageId("A")),
            edges = listOf(edge("t2", "A", "B"), edge("t2b", "B", "A"))
        )

        val result = CycleCanonicalizer.canonicalize(listOf(cycleWithT1, cycleWithT2))

        assertEquals(2, result.size)
    }

    @Test
    fun `two rotations of the same cycle dedup to one entry`() {
        // Cycle A -> B -> C -> A, represented starting at B or starting at A
        val eAB = edge("t1", "A", "B")
        val eBC = edge("t2", "B", "C")
        val eCA = edge("t3", "C", "A")

        val startAtA = DetectedCycle(
            nodes = listOf(StageId("A"), StageId("B"), StageId("C"), StageId("A")),
            edges = listOf(eAB, eBC, eCA)
        )
        val startAtB = DetectedCycle(
            nodes = listOf(StageId("B"), StageId("C"), StageId("A"), StageId("B")),
            edges = listOf(eBC, eCA, eAB)
        )

        val result = CycleCanonicalizer.canonicalize(listOf(startAtA, startAtB))

        assertEquals(1, result.size)
    }
}
