import { getLogger as getLogger$1 } from "../../../logger.js";
import runDbClient_default from "../../../data/db/runDbClient.js";
import { TaskState, createMessage, createTask, generateId, updateTask } from "@inkeep/agents-core";
import { streamSSE } from "hono/streaming";

//#region src/domains/run/a2a/handlers.ts
const logger = getLogger$1("a2aHandler");
async function a2aHandler(c, agent) {
	try {
		const rpcRequest = c.get("requestBody");
		if (rpcRequest.jsonrpc !== "2.0") return c.json({
			jsonrpc: "2.0",
			error: {
				code: -32600,
				message: "Invalid Request - must be JSON-RPC 2.0"
			},
			id: rpcRequest.id
		});
		switch (rpcRequest.method) {
			case "message/send": return await handleMessageSend(c, agent, rpcRequest);
			case "message/stream": return await handleMessageStream(c, agent, rpcRequest);
			case "tasks/get": return await handleTasksGet(c, agent, rpcRequest);
			case "tasks/cancel": return await handleTasksCancel(c, agent, rpcRequest);
			case "tasks/resubscribe": return await handleTasksResubscribe(c, agent, rpcRequest);
			case "agent.invoke": return await handleAgentInvoke(c, agent, rpcRequest);
			case "agent.getCapabilities": return await handleGetCapabilities(c, agent, rpcRequest);
			case "agent.getStatus": return await handleGetStatus(c, agent, rpcRequest);
			default: return c.json({
				jsonrpc: "2.0",
				error: {
					code: -32601,
					message: `Method not found: ${rpcRequest.method}`
				},
				id: rpcRequest.id
			});
		}
	} catch (error) {
		console.error("A2A Handler Error:", error);
		return c.json({
			jsonrpc: "2.0",
			error: {
				code: -32700,
				message: "Parse error"
			},
			id: null
		});
	}
}
async function handleMessageSend(c, agent, request) {
	try {
		const params = request.params;
		const { agentId, resolvedRef } = c.get("executionContext");
		const forwardedHeaders = {};
		const xForwardedCookie = c.req.header("x-forwarded-cookie");
		const cookie = c.req.header("cookie");
		if (xForwardedCookie) forwardedHeaders["x-forwarded-cookie"] = xForwardedCookie;
		else if (cookie) forwardedHeaders["x-forwarded-cookie"] = cookie;
		const mergedForwardedHeaders = {
			...params.message.metadata?.forwardedHeaders || {},
			...forwardedHeaders
		};
		const task = {
			id: generateId(),
			input: { parts: params.message.parts },
			context: {
				conversationId: params.message.contextId,
				metadata: {
					blocking: params.configuration?.blocking ?? false,
					custom: { agent_id: agentId || "" },
					...params.message.metadata,
					forwardedHeaders: Object.keys(mergedForwardedHeaders).length > 0 ? mergedForwardedHeaders : void 0
				}
			}
		};
		let effectiveContextId = params.message?.contextId;
		if (!effectiveContextId || effectiveContextId === "default") effectiveContextId = task.context?.conversationId;
		if (!effectiveContextId || effectiveContextId === "default") {
			if (params.message?.metadata?.conversationId && params.message.metadata.conversationId !== "default") effectiveContextId = params.message.metadata.conversationId;
		}
		if (!effectiveContextId || effectiveContextId === "default") effectiveContextId = "default";
		try {
			if (params.message && Object.keys(params.message).length > 0) JSON.stringify(params.message);
			else {
				JSON.stringify({
					role: "agent",
					parts: [{
						text: "Delegation task",
						kind: "text"
					}],
					contextId: effectiveContextId,
					messageId: task.id,
					kind: "message"
				});
				logger.warn({
					taskId: task.id,
					subAgentId: agent.subAgentId,
					originalMessage: params.message
				}, "Created fallback message content for empty delegation message");
			}
		} catch (error) {
			logger.error({
				error,
				taskId: task.id
			}, "Failed to serialize message");
			JSON.stringify({
				error: "Failed to serialize message",
				taskId: task.id,
				contextId: effectiveContextId,
				parts: [{
					text: "Error in delegation",
					kind: "text"
				}]
			});
		}
		logger.info({
			originalContextId: params.message.contextId,
			taskContextId: task.context?.conversationId,
			metadataContextId: params.message.metadata?.conversationId,
			finalContextId: effectiveContextId,
			subAgentId: agent.subAgentId
		}, "A2A contextId resolution for delegation");
		await createTask(runDbClient_default)({
			id: task.id,
			tenantId: agent.tenantId,
			projectId: agent.projectId,
			agentId: agentId || "",
			contextId: effectiveContextId,
			status: "working",
			metadata: {
				conversation_id: effectiveContextId,
				message_id: params.message.messageId || "",
				created_at: (/* @__PURE__ */ new Date()).toISOString(),
				updated_at: (/* @__PURE__ */ new Date()).toISOString(),
				sub_agent_id: agent.subAgentId,
				agent_id: agentId || "",
				stream_request_id: params.message.metadata?.stream_request_id
			},
			ref: resolvedRef,
			subAgentId: agent.subAgentId,
			createdAt: (/* @__PURE__ */ new Date()).toISOString(),
			updatedAt: (/* @__PURE__ */ new Date()).toISOString()
		});
		logger.info({ metadata: params.message.metadata }, "message metadata");
		if (params.message.metadata?.fromSubAgentId || params.message.metadata?.fromExternalAgentId || params.message.metadata?.fromTeamAgentId) {
			const messageText = params.message.parts.filter((part) => part.kind === "text" && "text" in part && part.text).map((part) => part.text).join(" ");
			try {
				const messageData = {
					id: generateId(),
					tenantId: agent.tenantId,
					projectId: agent.projectId,
					conversationId: effectiveContextId,
					role: "agent",
					content: { text: messageText },
					visibility: params.message.metadata?.fromExternalAgentId ? "external" : "internal",
					messageType: "a2a-request",
					taskId: task.id
				};
				if (params.message.metadata?.fromSubAgentId) {
					messageData.fromSubAgentId = params.message.metadata.fromSubAgentId;
					messageData.toSubAgentId = agent.subAgentId;
				} else if (params.message.metadata?.fromExternalAgentId) {
					messageData.fromExternalAgentId = params.message.metadata.fromExternalAgentId;
					messageData.toSubAgentId = agent.subAgentId;
				} else if (params.message.metadata?.fromTeamAgentId) {
					messageData.fromTeamAgentId = params.message.metadata.fromTeamAgentId;
					messageData.toTeamAgentId = agent.subAgentId;
				}
				await createMessage(runDbClient_default)(messageData);
				logger.info({
					fromSubAgentId: params.message.metadata.fromSubAgentId,
					fromExternalAgentId: params.message.metadata.fromExternalAgentId,
					fromTeamAgentId: params.message.metadata.fromTeamAgentId,
					toSubAgentId: agent.subAgentId,
					toTeamAgentId: params.message.metadata.fromTeamAgentId ? agent.subAgentId : void 0,
					conversationId: effectiveContextId,
					messageType: "a2a-request",
					taskId: task.id
				}, "A2A message stored in database");
			} catch (error) {
				logger.error({
					error,
					fromSubAgentId: params.message.metadata.fromSubAgentId,
					fromExternalAgentId: params.message.metadata.fromExternalAgentId,
					fromTeamAgentId: params.message.metadata.fromTeamAgentId,
					toSubAgentId: agent.subAgentId,
					conversationId: effectiveContextId
				}, "Failed to store A2A message in database");
			}
		}
		const result = await agent.taskHandler(task);
		await updateTask(runDbClient_default)({
			taskId: task.id,
			data: {
				status: result.status.state.toLowerCase(),
				metadata: {
					conversation_id: params.message.contextId || "",
					message_id: params.message.messageId || "",
					created_at: (/* @__PURE__ */ new Date()).toISOString(),
					updated_at: (/* @__PURE__ */ new Date()).toISOString(),
					sub_agent_id: agent.subAgentId,
					agent_id: agentId || ""
				}
			}
		});
		const transferArtifact = result.artifacts?.find((artifact) => artifact.parts?.some((part) => part.kind === "data" && part.data && typeof part.data === "object" && part.data.type === "transfer"));
		if (transferArtifact) {
			const transferPart = transferArtifact.parts?.find((part) => part.kind === "data" && part.data && typeof part.data === "object" && part.data.type === "transfer");
			if (transferPart && transferPart.kind === "data" && transferPart.data) {
				logger.info({ transferPart }, "transferPart");
				return c.json({
					jsonrpc: "2.0",
					result: {
						kind: "task",
						contextId: params.message.contextId,
						id: task.id,
						status: {
							state: TaskState.Completed,
							timestamp: (/* @__PURE__ */ new Date()).toISOString()
						},
						artifacts: [{
							artifactId: generateId(),
							parts: [{
								kind: "data",
								data: {
									type: "transfer",
									targetSubAgentId: transferPart.data.targetSubAgentId,
									fromSubAgentId: transferPart.data.fromSubAgentId
								}
							}, {
								kind: "text",
								text: transferPart.data.reason || "Agent requested transfer"
							}]
						}]
					},
					id: request.id
				});
			}
		}
		if (result.status.state === TaskState.Failed) {
			if (result.status.type === "connection_refused") return c.json({
				jsonrpc: "2.0",
				error: {
					code: -32603,
					message: result.status.message || "Agent execution failed",
					data: { type: "connection_refused" }
				}
			});
		}
		const taskStatus = {
			state: result.status.state,
			timestamp: (/* @__PURE__ */ new Date()).toISOString()
		};
		if (params.configuration?.blocking === false) {
			const taskResponse = {
				id: task.id,
				contextId: params.message.contextId || generateId(),
				status: taskStatus,
				artifacts: result.artifacts,
				kind: "task"
			};
			return c.json({
				jsonrpc: "2.0",
				result: taskResponse,
				id: request.id
			});
		}
		const messageResponse = {
			messageId: generateId(),
			parts: result.artifacts?.[0]?.parts || [{
				kind: "text",
				text: "Task completed successfully"
			}],
			role: "agent",
			taskId: task.id,
			contextId: params.message.contextId,
			kind: "message"
		};
		return c.json({
			jsonrpc: "2.0",
			result: messageResponse,
			id: request.id
		});
	} catch (error) {
		logger.error({
			error: error instanceof Error ? error.message : "Unknown error",
			stack: error instanceof Error ? error.stack : void 0,
			subAgentId: agent.subAgentId
		}, "Error in handleMessageSend");
		return c.json({
			jsonrpc: "2.0",
			error: {
				code: -32603,
				message: "Internal error during message send",
				data: error instanceof Error ? error.message : "Unknown error"
			},
			id: request.id
		});
	}
}
async function handleMessageStream(c, agent, request) {
	try {
		const params = request.params;
		const { agentId } = c.get("executionContext");
		if (!agent.agentCard.capabilities.streaming) return c.json({
			jsonrpc: "2.0",
			error: {
				code: -32604,
				message: "Agent does not support streaming"
			},
			id: request.id
		});
		const forwardedHeaders = {};
		const xForwardedCookie = c.req.header("x-forwarded-cookie");
		const cookie = c.req.header("cookie");
		if (xForwardedCookie) forwardedHeaders["x-forwarded-cookie"] = xForwardedCookie;
		else if (cookie) forwardedHeaders["x-forwarded-cookie"] = cookie;
		const task = {
			id: generateId(),
			input: { parts: params.message.parts },
			context: {
				conversationId: params.message.contextId,
				metadata: {
					blocking: false,
					custom: { agent_id: agentId || "" },
					forwardedHeaders: Object.keys(forwardedHeaders).length > 0 ? forwardedHeaders : void 0
				}
			}
		};
		return streamSSE(c, async (stream$1) => {
			try {
				const initialTask = {
					id: task.id,
					contextId: params.message.contextId || generateId(),
					status: {
						state: TaskState.Working,
						timestamp: (/* @__PURE__ */ new Date()).toISOString()
					},
					artifacts: [],
					kind: "task"
				};
				await stream$1.writeSSE({ data: JSON.stringify({
					jsonrpc: "2.0",
					result: initialTask,
					id: request.id
				}) });
				const result = await agent.taskHandler(task);
				const transferArtifact = result.artifacts?.find((artifact) => artifact.parts?.some((part) => part.kind === "data" && part.data && typeof part.data === "object" && part.data.type === "transfer"));
				if (transferArtifact) {
					const transferPart = transferArtifact.parts?.find((part) => part.kind === "data" && part.data && typeof part.data === "object" && part.data.type === "transfer");
					if (transferPart && transferPart.kind === "data" && transferPart.data) {
						await stream$1.writeSSE({ data: JSON.stringify({
							jsonrpc: "2.0",
							result: {
								type: "transfer",
								target: transferPart.data.targetSubAgentId,
								task_id: task.id,
								reason: transferPart.data.reason || "Agent requested transfer",
								original_message: transferPart.data.original_message,
								context: {
									conversationId: params.message.contextId,
									tenantId: agent.tenantId,
									transfer_context: result.artifacts
								}
							},
							id: request.id
						}) });
						return;
					}
				}
				const messageResponse = {
					messageId: generateId(),
					parts: result.artifacts?.[0]?.parts || [{
						kind: "text",
						text: "Task completed successfully"
					}],
					role: "agent",
					taskId: task.id,
					contextId: params.message.contextId,
					kind: "message"
				};
				await stream$1.writeSSE({ data: JSON.stringify({
					jsonrpc: "2.0",
					result: messageResponse,
					id: request.id
				}) });
				const completedTask = {
					...initialTask,
					status: {
						state: TaskState.Completed,
						timestamp: (/* @__PURE__ */ new Date()).toISOString()
					},
					artifacts: result.artifacts
				};
				await stream$1.writeSSE({ data: JSON.stringify({
					jsonrpc: "2.0",
					result: completedTask,
					id: request.id
				}) });
			} catch (error) {
				console.error("Error in stream execution:", error);
				await stream$1.writeSSE({ data: JSON.stringify({
					jsonrpc: "2.0",
					error: {
						code: -32603,
						message: "Internal error during streaming execution",
						data: error instanceof Error ? error.message : "Unknown error"
					},
					id: request.id
				}) });
			}
		});
	} catch (error) {
		return c.json({
			jsonrpc: "2.0",
			error: {
				code: -32603,
				message: "Internal error during message stream setup",
				data: error instanceof Error ? error.message : "Unknown error"
			},
			id: request.id
		});
	}
}
async function handleTasksGet(c, _agent, request) {
	try {
		const params = request.params;
		const task = {
			id: params.id,
			contextId: generateId(),
			status: {
				state: TaskState.Completed,
				timestamp: (/* @__PURE__ */ new Date()).toISOString()
			},
			artifacts: [{
				artifactId: generateId(),
				parts: [{
					kind: "text",
					text: `Task ${params.id} completed successfully`
				}],
				createdAt: (/* @__PURE__ */ new Date()).toISOString()
			}],
			kind: "task"
		};
		return c.json({
			jsonrpc: "2.0",
			result: task,
			id: request.id
		});
	} catch (error) {
		return c.json({
			jsonrpc: "2.0",
			error: {
				code: -32603,
				message: "Internal error getting task",
				data: error instanceof Error ? error.message : "Unknown error"
			},
			id: request.id
		});
	}
}
async function handleTasksCancel(c, _agent, request) {
	try {
		request.params;
		return c.json({
			jsonrpc: "2.0",
			result: { success: true },
			id: request.id
		});
	} catch (error) {
		return c.json({
			jsonrpc: "2.0",
			error: {
				code: -32603,
				message: "Internal error canceling task",
				data: error instanceof Error ? error.message : "Unknown error"
			},
			id: request.id
		});
	}
}
async function handleAgentInvoke(c, agent, request) {
	try {
		const task = request.params;
		const result = await agent.taskHandler(task);
		return c.json({
			jsonrpc: "2.0",
			result,
			id: request.id
		});
	} catch (error) {
		return c.json({
			jsonrpc: "2.0",
			error: {
				code: -32603,
				message: "Internal error during agent invocation",
				data: error instanceof Error ? error.message : "Unknown error"
			},
			id: request.id
		});
	}
}
async function handleGetCapabilities(c, agent, request) {
	return c.json({
		jsonrpc: "2.0",
		result: agent.agentCard.capabilities,
		id: request.id
	});
}
async function handleGetStatus(c, agent, request) {
	return c.json({
		jsonrpc: "2.0",
		result: {
			status: "ready",
			subAgentId: agent.subAgentId
		},
		id: request.id
	});
}
async function handleTasksResubscribe(c, agent, request) {
	try {
		const params = request.params;
		if (!agent.agentCard.capabilities.streaming) return c.json({
			jsonrpc: "2.0",
			error: {
				code: -32604,
				message: "Agent does not support streaming for resubscription"
			},
			id: request.id
		});
		return streamSSE(c, async (stream$1) => {
			try {
				const task = {
					id: params.taskId,
					contextId: generateId(),
					status: {
						state: TaskState.Completed,
						timestamp: (/* @__PURE__ */ new Date()).toISOString()
					},
					artifacts: [],
					kind: "task"
				};
				await stream$1.writeSSE({ data: JSON.stringify({
					jsonrpc: "2.0",
					result: task,
					id: request.id
				}) });
			} catch (error) {
				console.error("Error in task resubscription:", error);
				await stream$1.writeSSE({ data: JSON.stringify({
					jsonrpc: "2.0",
					error: {
						code: -32603,
						message: "Internal error during task resubscription",
						data: error instanceof Error ? error.message : "Unknown error"
					},
					id: request.id
				}) });
			}
		});
	} catch (error) {
		return c.json({
			jsonrpc: "2.0",
			error: {
				code: -32603,
				message: "Internal error during task resubscription setup",
				data: error instanceof Error ? error.message : "Unknown error"
			},
			id: request.id
		});
	}
}

//#endregion
export { a2aHandler };