package com.correx.infrastructure.tools.task

import com.correx.core.approvals.Tier
import com.correx.core.events.events.ToolRequest
import com.correx.core.events.types.ProjectId
import com.correx.core.tasks.TaskService
import com.correx.core.tools.contract.Tool
import com.correx.core.tools.contract.ToolCapability
import com.correx.core.tools.contract.ToolExecutor
import com.correx.core.tools.contract.ToolResult
import com.correx.core.tools.contract.ValidationResult
import kotlinx.serialization.json.JsonObject
import kotlinx.serialization.json.buildJsonObject
import kotlinx.serialization.json.put
import kotlinx.serialization.json.putJsonObject

private const val DEFAULT_LIMIT = 20

/**
 * Agent-facing tool: list tasks that are ready to be worked right now — TODO with every dependency
 * satisfied. Read-only, lowest tier. This is how an agent looking for work discovers what it can
 * pick up; it then claims one with `task_update action=claim`. It surfaces work, it does not assign.
 */
class TaskReadyTool(private val service: TaskService) : Tool, ToolExecutor {

    override val name: String = "task_ready"
    override val description: String =
        "List tasks ready to work now — TODO with all dependencies satisfied — when you're looking " +
            "for what to pick up. Claim one with task_update action=claim. Optionally scope to a " +
            "project. Returns 'id [STATUS] title' lines."
    override val parametersSchema: JsonObject = buildJsonObject {
        put("type", "object")
        putJsonObject("properties") {
            putJsonObject("project") {
                put("type", "string")
                put("description", "Limit to a project (e.g. 'auth'). Omit for the whole board.")
            }
            putJsonObject("limit") {
                put("type", "integer")
                put("description", "Max results (default $DEFAULT_LIMIT).")
            }
        }
    }
    override val tier: Tier = Tier.T1
    override val requiredCapabilities: Set<ToolCapability> = emptySet()

    override fun validateRequest(request: ToolRequest): ValidationResult = ValidationResult.Valid

    override suspend fun execute(request: ToolRequest): ToolResult {
        val project = request.stringParam("project")?.let { ProjectId(it) }
        val limit = (request.parameters["limit"] as? Number)?.toInt()?.takeIf { it > 0 } ?: DEFAULT_LIMIT
        val ready = service.ready(project).take(limit)
        val output = if (ready.isEmpty()) {
            "no ready tasks"
        } else {
            ready.joinToString("\n") {
                "${it.taskId.value} [${it.state.status.name}] ${it.state.title.orEmpty()}".trimEnd()
            }
        }
        return ToolResult.Success(
            invocationId = request.invocationId,
            output = output,
            metadata = mapOf("count" to ready.size.toString()),
        )
    }
}
