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.TaskId
import com.correx.core.tasks.TaskContextAssembler
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.JsonPrimitive
import kotlinx.serialization.json.add
import kotlinx.serialization.json.buildJsonArray
import kotlinx.serialization.json.buildJsonObject
import kotlinx.serialization.json.put
import kotlinx.serialization.json.putJsonObject

/**
 * Agent-facing tool: fetch a task's token-optimized context bundle in one call. Read-only, so
 * it sits at the lowest tier (like file_read) — agents call it before starting work on a task.
 */
class TaskContextTool(private val assembler: TaskContextAssembler) : Tool, ToolExecutor {

    override val name: String = "task_context"
    override val description: String =
        "Call this first, before working a task you've claimed or been pointed at, so you don't " +
            "re-derive context: it returns the task's goal, acceptance criteria, resolved " +
            "dependencies, related links, relevant files, and notes in one bundle."
    override val parametersSchema: JsonObject = buildJsonObject {
        put("type", "object")
        putJsonObject("properties") {
            putJsonObject("id") { put("type", "string"); put("description", "Task id, e.g. 'auth-142'.") }
        }
        put("required", buildJsonArray { add(JsonPrimitive("id")) })
    }
    override val tier: Tier = Tier.T1
    override val requiredCapabilities: Set<ToolCapability> = emptySet()

    override fun validateRequest(request: ToolRequest): ValidationResult {
        request.stringParam("id") ?: return ValidationResult.Invalid("Missing 'id' (string).")
        return ValidationResult.Valid
    }

    override suspend fun execute(request: ToolRequest): ToolResult {
        val id = request.stringParam("id")
            ?: return ToolResult.Failure(request.invocationId, "Missing 'id' (string).", recoverable = false)
        val bundle = assembler.assemble(TaskId(id))
            ?: return ToolResult.Failure(request.invocationId, "No such task: $id", recoverable = false)
        return ToolResult.Success(
            invocationId = request.invocationId,
            output = bundle.render(),
            metadata = mapOf("taskId" to id, "status" to bundle.status),
        )
    }
}
