package com.correx.infrastructure.tools.task

import com.correx.core.events.events.ToolRequest
import com.correx.core.events.types.TaskId
import com.correx.core.events.types.TaskLinkType
import com.correx.core.events.types.TaskTargetKind
import com.correx.core.tasks.TaskService

/** A non-blank string parameter, or null when absent/blank/not a string. */
internal fun ToolRequest.stringParam(name: String): String? =
    (parameters[name] as? String)?.takeIf { it.isNotBlank() }

/** A string-list parameter (JSON array), coerced element-wise; empty when absent. */
internal fun ToolRequest.listParam(name: String): List<String> =
    (parameters[name] as? List<*>)?.mapNotNull { it?.toString()?.takeIf(String::isNotBlank) } ?: emptyList()

/** A boolean parameter, accepting a real Boolean or the string "true" (case-insensitive). */
internal fun ToolRequest.boolParam(name: String): Boolean =
    parameters[name] == true || stringParam(name)?.toBoolean() == true

/**
 * Records the agent's session on the task as a CONTEXT/SESSION link, so the context bundle can
 * surface the run(s) that created or worked on it (the session resolver inlines status/intent).
 * No-op for a blank session id; duplicate links are deduped by the reducer, so creating and then
 * claiming from the same session yields a single edge.
 */
internal suspend fun TaskService.linkOriginSession(taskId: TaskId, request: ToolRequest) {
    val session = request.sessionId.value.takeIf { it.isNotBlank() } ?: return
    link(taskId, session, TaskLinkType.CONTEXT, TaskTargetKind.SESSION)
}
