import { getLogger } from "../../../logger.js";
import { generateDescriptionWithRelationData } from "../data/agents.js";

//#region src/domains/run/utils/project.ts
const logger = getLogger("project-helper");
/**
* Get an agent from the project definition
* Replaces direct database calls with lookup from pre-fetched project data
*/
function getAgentFromProject(params) {
	const { project, agentId } = params;
	const agent = project.agents[agentId];
	if (!agent) {
		logger.warn({ agentId }, "Agent not found in project");
		return null;
	}
	return agent;
}
/**
* Get a sub-agent from the project definition
* Replaces direct database calls with lookup from pre-fetched project data
*/
function getSubAgentFromProject(params) {
	const { project, agentId, subAgentId } = params;
	const agent = project.agents[agentId];
	if (!agent) {
		logger.warn({ agentId }, "Agent not found in project");
		return null;
	}
	const targetSubAgentId = subAgentId || agent.defaultSubAgentId;
	if (!targetSubAgentId) {
		logger.warn({ agentId }, "No default sub-agent ID configured for agent");
		return null;
	}
	const subAgent = agent.subAgents?.[targetSubAgentId];
	if (!subAgent) {
		logger.warn({
			agentId,
			subAgentId: targetSubAgentId
		}, "Sub-agent not found in project");
		return null;
	}
	return subAgent;
}
/**
* Extract transfer relations from a sub-agent's canTransferTo array
* Returns sub-agents that can be transferred to with their details
*/
function extractTransferRelations(params) {
	const { agent, canTransferTo } = params;
	return canTransferTo.map((relation) => {
		const targetSubAgent = agent.subAgents?.[relation.subAgentId];
		if (targetSubAgent) return {
			id: relation.subAgentId,
			name: targetSubAgent.name,
			description: targetSubAgent.description,
			relationType: "transfer",
			relationId: relation.subAgentSubAgentRelationId
		};
		return null;
	}).filter((r) => r !== null);
}
/**
* Parse canDelegateTo array to separate internal, external, and team relations
* Handles the union type of string | CanDelegateToExternalAgent | CanDelegateToTeamAgent
*/
function parseDelegateRelations(params) {
	const { agent, project, canDelegateTo } = params;
	const internalDelegateRelations = [];
	const externalRelations = [];
	const teamRelations = [];
	for (const item of canDelegateTo) if ("subAgentId" in item) {
		const targetSubAgent = agent.subAgents?.[item.subAgentId];
		if (targetSubAgent) internalDelegateRelations.push({
			id: item.subAgentId,
			name: targetSubAgent.name,
			description: targetSubAgent.description,
			relationType: "delegate",
			relationId: item.subAgentSubAgentRelationId
		});
	} else if ("externalAgentId" in item) {
		const extAgentId = item.externalAgentId;
		const extHeaders = item.headers;
		const extRelationId = item.subAgentExternalAgentRelationId;
		const externalAgent = agent.externalAgents?.[extAgentId] || project.externalAgents?.[extAgentId];
		if (externalAgent) externalRelations.push({
			externalAgent: {
				id: extAgentId,
				name: externalAgent.name,
				description: externalAgent.description,
				baseUrl: externalAgent.baseUrl,
				credentialReferenceId: externalAgent.credentialReferenceId
			},
			headers: extHeaders,
			relationId: extRelationId
		});
	} else if ("agentId" in item) {
		const teamAgentId = item.agentId;
		const teamHeaders = item.headers;
		const teamRelationId = item.subAgentTeamAgentRelationId;
		const teamAgent = agent.teamAgents?.[teamAgentId];
		if (teamAgent) teamRelations.push({
			targetAgent: {
				id: teamAgentId,
				name: teamAgent.name,
				description: teamAgent.description
			},
			targetAgentId: teamAgentId,
			headers: teamHeaders,
			relationId: teamRelationId
		});
	}
	return {
		internalDelegateRelations,
		externalRelations,
		teamRelations
	};
}
/**
* Get all relations for a sub-agent (transfers + delegates combined)
* Convenience function that combines extractTransferRelations and parseDelegateRelations
*/
function getSubAgentRelations(params) {
	const { agent, project, subAgent } = params;
	const canTransferTo = subAgent.canTransferTo || [];
	const canDelegateTo = subAgent.canDelegateTo || [];
	const transferRelations = extractTransferRelations({
		agent,
		canTransferTo
	});
	const { internalDelegateRelations, externalRelations, teamRelations } = parseDelegateRelations({
		agent,
		project,
		canDelegateTo
	});
	return {
		transferRelations,
		internalDelegateRelations,
		externalRelations,
		teamRelations
	};
}
/**
* Get tools for a sub-agent from their canUse array
* Resolves tool references from both agent-level and project-level tools
*/
function getToolsForSubAgent(params) {
	const { agent, project, subAgent } = params;
	return (subAgent.canUse || []).map((canUseItem) => {
		const tool = agent.tools?.[canUseItem.toolId] || project.tools?.[canUseItem.toolId];
		if (!tool) return null;
		return {
			toolId: canUseItem.toolId,
			tool,
			selectedTools: canUseItem.toolSelection,
			headers: canUseItem.headers,
			toolPolicies: canUseItem.toolPolicies,
			relationshipId: canUseItem.agentToolRelationId
		};
	}).filter((item) => item !== null);
}
/**
* Get data components for a sub-agent
* Resolves data component references from project-level dataComponents
*/
function getDataComponentsForSubAgent(params) {
	const { project, subAgent } = params;
	const dataComponentIds = subAgent.dataComponents || [];
	const dataComponentsMap = project.dataComponents || {};
	return dataComponentIds.map((id) => dataComponentsMap[id]).filter((c) => c !== null && c !== void 0);
}
/**
* Get artifact components for a sub-agent
* Resolves artifact component references from project-level artifactComponents
*/
function getArtifactComponentsForSubAgent(params) {
	const { project, subAgent } = params;
	const artifactComponentIds = subAgent.artifactComponents || [];
	const artifactComponentsMap = project.artifactComponents || {};
	return artifactComponentIds.map((id) => artifactComponentsMap[id]).filter((c) => c !== null && c !== void 0);
}
/**
* Get transfer relations for a target sub-agent
* Used when building agent configurations that need to know what the target can transfer to
*/
function getTransferRelationsForTargetSubAgent(params) {
	const { agent, subAgentId } = params;
	const targetSubAgent = agent.subAgents?.[subAgentId];
	if (!targetSubAgent) return [];
	return (targetSubAgent.canTransferTo || []).map((relation) => {
		const target = agent.subAgents?.[relation.subAgentId];
		return target ? {
			id: relation.subAgentId,
			name: target.name,
			description: target.description,
			relationId: relation.subAgentSubAgentRelationId
		} : null;
	}).filter((r) => r !== null);
}
/**
* Get delegate relations (external agents) for a target sub-agent
* Used when building agent configurations that need to know what external agents the target can delegate to
*/
function getExternalAgentRelationsForTargetSubAgent(params) {
	const { agent, project, subAgentId } = params;
	const targetSubAgent = agent.subAgents?.[subAgentId];
	if (!targetSubAgent) return [];
	return (targetSubAgent.canDelegateTo || []).filter((item) => typeof item === "object" && item !== null && "externalAgentId" in item).map((item) => {
		const extAgent = agent.externalAgents?.[item.externalAgentId] || project.externalAgents?.[item.externalAgentId];
		return extAgent ? {
			externalAgent: {
				...extAgent,
				id: item.externalAgentId
			},
			headers: item.headers,
			relationId: item.subAgentExternalAgentRelationId
		} : null;
	}).filter((r) => r !== null);
}
/**
* Build relation arrays from a sub-agent's canTransferTo and canDelegateTo
* Used for generating enhanced descriptions
*/
function buildRelationsForDescription(params) {
	const { agent, project, subAgent } = params;
	const canTransferTo = subAgent.canTransferTo || [];
	const canDelegateTo = subAgent.canDelegateTo || [];
	const internalRelations = canTransferTo.map((relation) => {
		const target = agent.subAgents?.[relation.subAgentId];
		return target ? {
			id: relation.subAgentId,
			name: target.name,
			description: target.description,
			relationType: "transfer",
			relationId: relation.subAgentSubAgentRelationId
		} : null;
	}).filter((r) => r !== null);
	const externalRelations = [];
	const teamRelations = [];
	for (const item of canDelegateTo) if ("externalAgentId" in item) {
		const extId = item.externalAgentId;
		const extAgent = agent.externalAgents?.[extId] || project.externalAgents?.[extId];
		if (extAgent) externalRelations.push({
			externalAgent: {
				id: extId,
				name: extAgent.name,
				description: extAgent.description
			},
			relationId: item.subAgentExternalAgentRelationId
		});
	} else if ("agentId" in item) {
		const tId = item.agentId;
		const tAgent = agent.teamAgents?.[tId];
		if (tAgent) teamRelations.push({
			targetAgent: {
				id: tId,
				name: tAgent.name,
				description: tAgent.description
			},
			targetAgentId: tId,
			relationId: item.subAgentTeamAgentRelationId
		});
	}
	return {
		internalRelations,
		externalRelations,
		teamRelations
	};
}
/**
* Enhance an internal relation with a generated description
* Looks up the related sub-agent and builds relation data for description generation
*/
function enhanceInternalRelation(params) {
	const { relation, agent, project } = params;
	const relatedSubAgent = agent.subAgents?.[relation.id];
	if (!relatedSubAgent) return relation;
	const { internalRelations, externalRelations, teamRelations } = buildRelationsForDescription({
		agent,
		project,
		subAgent: relatedSubAgent
	});
	const enhancedDescription = generateDescriptionWithRelationData(relation.description || "", internalRelations, externalRelations, teamRelations);
	return {
		...relation,
		description: enhancedDescription
	};
}
/**
* Enhance a team relation with a generated description
* Looks up the team agent's default sub-agent and builds relation data for description generation
*/
function enhanceTeamRelation(params) {
	const { relation, project } = params;
	const teamAgent = project.agents[relation.targetAgentId];
	if (!teamAgent?.defaultSubAgentId) return relation;
	const defaultSubAgent = teamAgent.subAgents?.[teamAgent.defaultSubAgentId];
	if (!defaultSubAgent) return relation;
	const { internalRelations, externalRelations, teamRelations } = buildRelationsForDescription({
		agent: teamAgent,
		project,
		subAgent: defaultSubAgent
	});
	const enhancedDescription = generateDescriptionWithRelationData(teamAgent.description || "", internalRelations, externalRelations, teamRelations);
	return {
		...relation,
		targetAgent: {
			...relation.targetAgent,
			description: enhancedDescription
		}
	};
}

//#endregion
export { buildRelationsForDescription, enhanceInternalRelation, enhanceTeamRelation, extractTransferRelations, getAgentFromProject, getArtifactComponentsForSubAgent, getDataComponentsForSubAgent, getExternalAgentRelationsForTargetSubAgent, getSubAgentFromProject, getSubAgentRelations, getToolsForSubAgent, getTransferRelationsForTargetSubAgent, parseDelegateRelations };