import { externalAgents, subAgentExternalAgentRelations, subAgents } from "../../db/manage/manage-schema.js";
import { deriveRelationId } from "../../utils/conversations.js";
import { agentScopedWhere, subAgentScopedWhere } from "./scope-helpers.js";
import { and, count, desc, eq } from "drizzle-orm";

//#region src/data-access/manage/subAgentExternalAgentRelations.ts
const getSubAgentExternalAgentRelationById = (db) => async (params) => {
	return db.query.subAgentExternalAgentRelations.findFirst({ where: and(subAgentScopedWhere(subAgentExternalAgentRelations, params.scopes), eq(subAgentExternalAgentRelations.id, params.relationId)) });
};
const listSubAgentExternalAgentRelations = (db) => async (params) => {
	const page = params.pagination?.page || 1;
	const limit = Math.min(params.pagination?.limit || 10, 100);
	const offset = (page - 1) * limit;
	const whereClause = subAgentScopedWhere(subAgentExternalAgentRelations, params.scopes);
	const [data, totalResult] = await Promise.all([db.select().from(subAgentExternalAgentRelations).where(whereClause).limit(limit).offset(offset).orderBy(desc(subAgentExternalAgentRelations.createdAt)), db.select({ count: count() }).from(subAgentExternalAgentRelations).where(whereClause)]);
	const total = totalResult[0]?.count || 0;
	return {
		data,
		pagination: {
			page,
			limit,
			total,
			pages: Math.ceil(total / limit)
		}
	};
};
const getSubAgentExternalAgentRelations = (db) => async (params) => {
	return await db.query.subAgentExternalAgentRelations.findMany({ where: subAgentScopedWhere(subAgentExternalAgentRelations, params.scopes) });
};
const getSubAgentExternalAgentRelationsByAgent = (db) => async (params) => {
	return await db.query.subAgentExternalAgentRelations.findMany({ where: agentScopedWhere(subAgentExternalAgentRelations, params.scopes) });
};
const getSubAgentExternalAgentRelationsByExternalAgent = (db) => async (params) => {
	const page = params.pagination?.page || 1;
	const limit = Math.min(params.pagination?.limit || 10, 100);
	const offset = (page - 1) * limit;
	const whereClause = and(agentScopedWhere(subAgentExternalAgentRelations, params.scopes), eq(subAgentExternalAgentRelations.externalAgentId, params.externalAgentId));
	const [data, totalResult] = await Promise.all([db.select().from(subAgentExternalAgentRelations).where(whereClause).limit(limit).offset(offset).orderBy(desc(subAgentExternalAgentRelations.createdAt)), db.select({ count: count() }).from(subAgentExternalAgentRelations).where(whereClause)]);
	const total = totalResult[0]?.count || 0;
	return {
		data,
		pagination: {
			page,
			limit,
			total,
			pages: Math.ceil(total / limit)
		}
	};
};
const getExternalAgentsForSubAgent = (db) => async (params) => {
	const page = params.pagination?.page || 1;
	const limit = Math.min(params.pagination?.limit || 10, 100);
	const offset = (page - 1) * limit;
	const [data, totalResult] = await Promise.all([db.select({
		id: subAgentExternalAgentRelations.id,
		tenantId: subAgentExternalAgentRelations.tenantId,
		projectId: subAgentExternalAgentRelations.projectId,
		agentId: subAgentExternalAgentRelations.agentId,
		subAgentId: subAgentExternalAgentRelations.subAgentId,
		externalAgentId: subAgentExternalAgentRelations.externalAgentId,
		headers: subAgentExternalAgentRelations.headers,
		createdAt: subAgentExternalAgentRelations.createdAt,
		updatedAt: subAgentExternalAgentRelations.updatedAt,
		externalAgent: {
			id: externalAgents.id,
			name: externalAgents.name,
			description: externalAgents.description,
			baseUrl: externalAgents.baseUrl,
			credentialReferenceId: externalAgents.credentialReferenceId,
			tenantId: externalAgents.tenantId,
			projectId: externalAgents.projectId,
			createdAt: externalAgents.createdAt,
			updatedAt: externalAgents.updatedAt
		}
	}).from(subAgentExternalAgentRelations).innerJoin(externalAgents, and(eq(subAgentExternalAgentRelations.tenantId, externalAgents.tenantId), eq(subAgentExternalAgentRelations.projectId, externalAgents.projectId), eq(subAgentExternalAgentRelations.externalAgentId, externalAgents.id))).where(subAgentScopedWhere(subAgentExternalAgentRelations, params.scopes)).limit(limit).offset(offset).orderBy(desc(subAgentExternalAgentRelations.createdAt)), db.select({ count: count() }).from(subAgentExternalAgentRelations).where(subAgentScopedWhere(subAgentExternalAgentRelations, params.scopes))]);
	const total = totalResult[0]?.count || 0;
	return {
		data,
		pagination: {
			page,
			limit,
			total,
			pages: Math.ceil(total / limit)
		}
	};
};
const getSubAgentsForExternalAgent = (db) => async (params) => {
	const page = params.pagination?.page || 1;
	const limit = Math.min(params.pagination?.limit || 10, 100);
	const offset = (page - 1) * limit;
	const [data, totalResult] = await Promise.all([db.select({
		id: subAgentExternalAgentRelations.id,
		tenantId: subAgentExternalAgentRelations.tenantId,
		projectId: subAgentExternalAgentRelations.projectId,
		agentId: subAgentExternalAgentRelations.agentId,
		subAgentId: subAgentExternalAgentRelations.subAgentId,
		externalAgentId: subAgentExternalAgentRelations.externalAgentId,
		headers: subAgentExternalAgentRelations.headers,
		createdAt: subAgentExternalAgentRelations.createdAt,
		updatedAt: subAgentExternalAgentRelations.updatedAt,
		subAgent: {
			id: subAgents.id,
			name: subAgents.name,
			description: subAgents.description,
			prompt: subAgents.prompt,
			conversationHistoryConfig: subAgents.conversationHistoryConfig,
			models: subAgents.models,
			stopWhen: subAgents.stopWhen,
			createdAt: subAgents.createdAt,
			updatedAt: subAgents.updatedAt
		}
	}).from(subAgentExternalAgentRelations).innerJoin(subAgents, and(eq(subAgentExternalAgentRelations.subAgentId, subAgents.id), eq(subAgentExternalAgentRelations.tenantId, subAgents.tenantId), eq(subAgentExternalAgentRelations.projectId, subAgents.projectId), eq(subAgentExternalAgentRelations.agentId, subAgents.agentId))).where(and(agentScopedWhere(subAgentExternalAgentRelations, params.scopes), eq(subAgentExternalAgentRelations.externalAgentId, params.externalAgentId))).limit(limit).offset(offset).orderBy(desc(subAgentExternalAgentRelations.createdAt)), db.select({ count: count() }).from(subAgentExternalAgentRelations).where(and(agentScopedWhere(subAgentExternalAgentRelations, params.scopes), eq(subAgentExternalAgentRelations.externalAgentId, params.externalAgentId)))]);
	const total = totalResult[0]?.count || 0;
	return {
		data,
		pagination: {
			page,
			limit,
			total,
			pages: Math.ceil(total / limit)
		}
	};
};
const createSubAgentExternalAgentRelation = (db) => async (params) => {
	const finalRelationId = params.relationId ?? deriveRelationId(params.scopes.tenantId, params.scopes.projectId, params.scopes.agentId, params.scopes.subAgentId, params.data.externalAgentId);
	return (await db.insert(subAgentExternalAgentRelations).values({
		id: finalRelationId,
		tenantId: params.scopes.tenantId,
		projectId: params.scopes.projectId,
		agentId: params.scopes.agentId,
		subAgentId: params.scopes.subAgentId,
		externalAgentId: params.data.externalAgentId,
		headers: params.data.headers
	}).returning())[0];
};
/**
* Check if sub-agent external agent relation exists by params
*/
const getSubAgentExternalAgentRelationByParams = (db) => async (params) => {
	return db.query.subAgentExternalAgentRelations.findFirst({ where: and(subAgentScopedWhere(subAgentExternalAgentRelations, params.scopes), eq(subAgentExternalAgentRelations.externalAgentId, params.externalAgentId)) });
};
/**
* Upsert sub-agent external agent relation (create if it doesn't exist, update if it does)
*/
const upsertSubAgentExternalAgentRelation = (db) => async (params) => {
	if (params.relationId) return await updateSubAgentExternalAgentRelation(db)({
		scopes: params.scopes,
		relationId: params.relationId,
		data: params.data
	});
	const existing = await getSubAgentExternalAgentRelationByParams(db)({
		scopes: params.scopes,
		externalAgentId: params.data.externalAgentId
	});
	if (existing) return await updateSubAgentExternalAgentRelation(db)({
		scopes: params.scopes,
		relationId: existing.id,
		data: params.data
	});
	return await createSubAgentExternalAgentRelation(db)(params);
};
const updateSubAgentExternalAgentRelation = (db) => async (params) => {
	const updateData = {
		...params.data,
		updatedAt: (/* @__PURE__ */ new Date()).toISOString()
	};
	return (await db.update(subAgentExternalAgentRelations).set(updateData).where(and(subAgentScopedWhere(subAgentExternalAgentRelations, params.scopes), eq(subAgentExternalAgentRelations.id, params.relationId))).returning())[0];
};
const deleteSubAgentExternalAgentRelation = (db) => async (params) => {
	return (await db.delete(subAgentExternalAgentRelations).where(and(subAgentScopedWhere(subAgentExternalAgentRelations, params.scopes), eq(subAgentExternalAgentRelations.id, params.relationId))).returning()).length > 0;
};
const deleteSubAgentExternalAgentRelationsBySubAgent = (db) => async (params) => {
	return (await db.delete(subAgentExternalAgentRelations).where(subAgentScopedWhere(subAgentExternalAgentRelations, params.scopes)).returning()).length > 0;
};
const deleteSubAgentExternalAgentRelationsByAgent = (db) => async (params) => {
	return (await db.delete(subAgentExternalAgentRelations).where(agentScopedWhere(subAgentExternalAgentRelations, params.scopes)).returning()).length > 0;
};

//#endregion
export { createSubAgentExternalAgentRelation, deleteSubAgentExternalAgentRelation, deleteSubAgentExternalAgentRelationsByAgent, deleteSubAgentExternalAgentRelationsBySubAgent, getExternalAgentsForSubAgent, getSubAgentExternalAgentRelationById, getSubAgentExternalAgentRelationByParams, getSubAgentExternalAgentRelations, getSubAgentExternalAgentRelationsByAgent, getSubAgentExternalAgentRelationsByExternalAgent, getSubAgentsForExternalAgent, listSubAgentExternalAgentRelations, updateSubAgentExternalAgentRelation, upsertSubAgentExternalAgentRelation };