package com.correx.core.kernel.retry

import com.correx.core.events.events.EventMetadata
import com.correx.core.events.events.NewEvent
import com.correx.core.events.events.RetryAttemptedEvent
import com.correx.core.events.execution.RetryPolicy
import com.correx.core.events.stores.EventStore
import com.correx.core.events.types.EventId
import com.correx.core.events.types.SessionId
import com.correx.core.events.types.StageId
import kotlinx.coroutines.delay
import kotlinx.datetime.Clock
import java.util.*

class DefaultRetryCoordinator(
    private val eventStore: EventStore,
) : RetryCoordinator {

    override suspend fun shouldRetry(
        sessionId: SessionId,
        stageId: StageId,
        currentAttempt: Int,
        policy: RetryPolicy,
        failureReason: String,
    ): Boolean {
        if (currentAttempt >= policy.maxAttempts) return false

        val eventId = EventId(UUID.randomUUID().toString())
        val event = NewEvent(
            metadata = EventMetadata(
                eventId = eventId,
                sessionId = sessionId,
                timestamp = Clock.System.now(),
                schemaVersion = 1,
                causationId = null,
                correlationId = null,
            ),
            payload = RetryAttemptedEvent(
                sessionId = sessionId,
                stageId = stageId,
                attemptNumber = currentAttempt + 1,
                maxAttempts = policy.maxAttempts,
                failureReason = failureReason,
            ),
        )

        eventStore.append(event)

        if (policy.backoffMs > 0L) {
            delay(policy.backoffMs)
        }

        return true
    }
}
