package com.correx.apps.server.tasks

import com.correx.core.events.types.SessionId
import com.correx.core.kernel.orchestration.TaskClaimCoordinator
import com.correx.core.tasks.TaskContextAssembler
import com.correx.core.tasks.TaskService

/**
 * [TaskClaimCoordinator] over the task projection: claims the session's next ready task (claimant =
 * session id) and renders its [TaskContextAssembler] bundle as the implementer's L0 context. The
 * claim emits a `TaskClaimedEvent`, so the task leaves `ready()` and the `tasks_ready` predicate can
 * eventually terminate the loop — driven by recorded fact, not agent compliance.
 */
class DefaultTaskClaimCoordinator(
    private val taskService: TaskService,
    private val assembler: TaskContextAssembler,
) : TaskClaimCoordinator {

    override suspend fun claimNext(sessionId: SessionId): String? {
        val active = taskService.activeClaim(sessionId.value)
        val task = active ?: taskService.nextReadyForSession(sessionId.value)
            ?.also { taskService.claim(it.taskId, sessionId.value) }
            ?: return null
        return assembler.assemble(task.taskId)?.render()
    }

    override fun activeScope(sessionId: SessionId): List<String> =
        taskService.activeClaim(sessionId.value)?.state?.affectedPaths ?: emptyList()

    override suspend fun blockActiveTask(sessionId: SessionId, reason: String) {
        taskService.activeClaim(sessionId.value)?.let { taskService.block(it.taskId, reason) }
    }
}
