import com.correx.core.approvals.GrantScope
import com.correx.core.approvals.Tier
import com.correx.core.approvals.domain.DefaultApprovalEngine
import com.correx.core.approvals.model.ApprovalContext
import com.correx.core.approvals.model.ApprovalGrant
import com.correx.core.approvals.model.ApprovalScopeIdentity
import com.correx.core.events.types.ApprovalDecisionId
import com.correx.core.events.types.GrantId
import com.correx.core.events.types.SessionId
import com.correx.core.sessions.ApprovalMode
import com.correx.testing.fixtures.request
import kotlinx.datetime.Instant
import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.Test

class ApprovalReplayTest {
    @Test
    fun `replaying same request with same inputs yields identical decision`() {
        val engine1 = DefaultApprovalEngine()
        val engine2 = DefaultApprovalEngine()
        val req = request("req1", Tier.T2)
        val ctx = ApprovalContext(
            ApprovalScopeIdentity(SessionId("s1"), null, null),
            ApprovalMode.AUTO
        )
        val grants = listOf(
            ApprovalGrant(
                GrantId("g1"),
                GrantScope.SESSION(),
                setOf(Tier.T2),
                "reason",
                Instant.parse("2026-01-01T00:00:00Z")
            )
        )
        val now = Instant.parse("2026-01-01T00:00:01Z")

        val d1 = engine1.evaluate(req, ctx, grants, now)
        val d2 = engine2.evaluate(req, ctx, grants, now)

        assertEquals(d1, d2)
    }

    @Test
    fun `decision ID determinism holds over multiple replays`() {
        val engine = DefaultApprovalEngine()
        val req = request("fixed", Tier.T3)
        val ctx = ApprovalContext(
            ApprovalScopeIdentity(SessionId("s"), null, null),
            ApprovalMode.PROMPT
        )
        val now = Instant.parse("2026-01-01T00:00:01Z")

        val d1 = engine.evaluate(req, ctx, emptyList(), now)
        val d2 = engine.evaluate(req, ctx, emptyList(), now)

        assertEquals(d1.id, d2.id)
        assertEquals(ApprovalDecisionId("decision:fixed"), d1.id)
    }
}
