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.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
import org.junit.jupiter.api.assertDoesNotThrow

class NoExecutionCouplingTest {

    @Test
    fun `engine does not mutate grants or context`() {
        val engine = DefaultApprovalEngine()
        val grants = mutableListOf(
            ApprovalGrant(
                GrantId("g1"),
                GrantScope.SESSION(),
                setOf(Tier.T2),
                "",
                Instant.parse("2026-01-01T00:00:00Z")
            )
        )
        val originalGrants = grants.toList()
        val ctx = ApprovalContext(
            ApprovalScopeIdentity(SessionId("s1"), null, null),
            ApprovalMode.DENY
        )
        val now = Instant.parse("2026-01-01T00:00:01Z")

        engine.evaluate(request("r1", Tier.T2), ctx, grants, now)

        assertEquals(originalGrants, grants, "Grants list must not be mutated")
        assertEquals(ApprovalMode.DENY, ctx.mode, "Context must not be mutated")
    }

    @Test
    fun `engine does not throw for valid input`() {
        val engine = DefaultApprovalEngine()
        assertDoesNotThrow {
            engine.evaluate(
                request("r1", Tier.T0),
                ApprovalContext(
                    ApprovalScopeIdentity(SessionId("s1"), null, null),
                    ApprovalMode.YOLO
                ),
                emptyList(),
                Instant.parse("2026-01-01T00:00:01Z")
            )
        }
    }
}
