import { webhookDestinationAgents, webhookDestinationEvaluators, webhookDestinations } from "../../db/manage/manage-schema.js";
import { generateId } from "../../utils/conversations.js";
import { projectScopedWhere } from "./scope-helpers.js";
import { and, count, desc, eq, inArray } from "drizzle-orm";

//#region src/data-access/manage/webhookDestinations.ts
const getWebhookDestinationById = (db) => async (params) => {
	const { scopes, webhookDestinationId } = params;
	return await db.query.webhookDestinations.findFirst({ where: and(projectScopedWhere(webhookDestinations, scopes), eq(webhookDestinations.id, webhookDestinationId)) });
};
const listWebhookDestinationsPaginated = (db) => async (params) => {
	const page = params.pagination?.page || 1;
	const limit = Math.min(params.pagination?.limit || 10, 100);
	const offset = (page - 1) * limit;
	const baseWhere = projectScopedWhere(webhookDestinations, params.scopes);
	if (!params.agentId) {
		const [data, totalResult] = await Promise.all([db.select().from(webhookDestinations).where(baseWhere).limit(limit).offset(offset).orderBy(desc(webhookDestinations.createdAt)), db.select({ count: count() }).from(webhookDestinations).where(baseWhere)]);
		const total$1 = totalResult[0]?.count || 0;
		return {
			data,
			pagination: {
				page,
				limit,
				total: total$1,
				pages: Math.ceil(total$1 / limit)
			}
		};
	}
	const agentId = params.agentId;
	const allDests = await db.select().from(webhookDestinations).where(baseWhere).orderBy(desc(webhookDestinations.createdAt));
	const destIds = allDests.map((d) => d.id);
	if (destIds.length === 0) return {
		data: [],
		pagination: {
			page,
			limit,
			total: 0,
			pages: 0
		}
	};
	const agentRows = await db.select().from(webhookDestinationAgents).where(and(eq(webhookDestinationAgents.tenantId, params.scopes.tenantId), eq(webhookDestinationAgents.projectId, params.scopes.projectId), inArray(webhookDestinationAgents.webhookDestinationId, destIds)));
	const agentsByDest = /* @__PURE__ */ new Map();
	for (const row of agentRows) {
		const list = agentsByDest.get(row.webhookDestinationId) ?? [];
		list.push(row.agentId);
		agentsByDest.set(row.webhookDestinationId, list);
	}
	const filtered = allDests.filter((dest) => {
		const agents = agentsByDest.get(dest.id);
		return !agents || agents.length === 0 || agents.includes(agentId);
	});
	const total = filtered.length;
	const pages = Math.ceil(total / limit);
	return {
		data: filtered.slice(offset, offset + limit),
		pagination: {
			page,
			limit,
			total,
			pages
		}
	};
};
const listEnabledWebhookDestinations = (db) => async (params) => {
	const { scopes, agentId } = params;
	const rows = await db.select({
		dest: webhookDestinations,
		scopedAgentId: webhookDestinationAgents.agentId,
		scopedEvaluatorId: webhookDestinationEvaluators.evaluatorId
	}).from(webhookDestinations).leftJoin(webhookDestinationAgents, and(eq(webhookDestinationAgents.tenantId, webhookDestinations.tenantId), eq(webhookDestinationAgents.projectId, webhookDestinations.projectId), eq(webhookDestinationAgents.webhookDestinationId, webhookDestinations.id))).leftJoin(webhookDestinationEvaluators, and(eq(webhookDestinationEvaluators.tenantId, webhookDestinations.tenantId), eq(webhookDestinationEvaluators.projectId, webhookDestinations.projectId), eq(webhookDestinationEvaluators.webhookDestinationId, webhookDestinations.id))).where(and(projectScopedWhere(webhookDestinations, scopes), eq(webhookDestinations.enabled, true)));
	if (rows.length === 0) return [];
	const destMap = /* @__PURE__ */ new Map();
	for (const row of rows) {
		const existing = destMap.get(row.dest.id);
		if (existing) {
			if (row.scopedAgentId) existing.agentIds.add(row.scopedAgentId);
			if (row.scopedEvaluatorId) existing.evaluatorIds.add(row.scopedEvaluatorId);
		} else destMap.set(row.dest.id, {
			dest: row.dest,
			agentIds: new Set(row.scopedAgentId ? [row.scopedAgentId] : []),
			evaluatorIds: new Set(row.scopedEvaluatorId ? [row.scopedEvaluatorId] : [])
		});
	}
	return Array.from(destMap.values()).filter(({ agentIds }) => agentIds.size === 0 || agentIds.has(agentId)).map(({ dest, agentIds, evaluatorIds }) => ({
		...dest,
		agentIds: Array.from(agentIds),
		evaluatorIds: Array.from(evaluatorIds)
	}));
};
const createWebhookDestination = (db) => async (params) => {
	return (await db.insert(webhookDestinations).values(params).returning())[0];
};
const updateWebhookDestination = (db) => async (params) => {
	const updateData = {
		...params.data,
		updatedAt: (/* @__PURE__ */ new Date()).toISOString()
	};
	return (await db.update(webhookDestinations).set(updateData).where(and(projectScopedWhere(webhookDestinations, params.scopes), eq(webhookDestinations.id, params.webhookDestinationId))).returning())[0];
};
const deleteWebhookDestination = (db) => async (params) => {
	return (await db.delete(webhookDestinations).where(and(projectScopedWhere(webhookDestinations, params.scopes), eq(webhookDestinations.id, params.webhookDestinationId))).returning()).length > 0;
};
const getWebhookDestinationAgentIds = (db) => async (params) => {
	return (await db.select({ agentId: webhookDestinationAgents.agentId }).from(webhookDestinationAgents).where(and(eq(webhookDestinationAgents.tenantId, params.scopes.tenantId), eq(webhookDestinationAgents.projectId, params.scopes.projectId), eq(webhookDestinationAgents.webhookDestinationId, params.webhookDestinationId)))).map((r) => r.agentId);
};
const setWebhookDestinationAgentIds = (db) => async (params) => {
	const { scopes, webhookDestinationId, agentIds } = params;
	await db.delete(webhookDestinationAgents).where(and(eq(webhookDestinationAgents.tenantId, scopes.tenantId), eq(webhookDestinationAgents.projectId, scopes.projectId), eq(webhookDestinationAgents.webhookDestinationId, webhookDestinationId)));
	if (agentIds.length > 0) await db.insert(webhookDestinationAgents).values(agentIds.map((agentId) => ({
		id: generateId(),
		tenantId: scopes.tenantId,
		projectId: scopes.projectId,
		webhookDestinationId,
		agentId
	})));
};
const getWebhookDestinationEvaluatorIds = (db) => async (params) => {
	return (await db.select({ evaluatorId: webhookDestinationEvaluators.evaluatorId }).from(webhookDestinationEvaluators).where(and(eq(webhookDestinationEvaluators.tenantId, params.scopes.tenantId), eq(webhookDestinationEvaluators.projectId, params.scopes.projectId), eq(webhookDestinationEvaluators.webhookDestinationId, params.webhookDestinationId)))).map((r) => r.evaluatorId);
};
const setWebhookDestinationEvaluatorIds = (db) => async (params) => {
	const { scopes, webhookDestinationId, evaluatorIds } = params;
	await db.delete(webhookDestinationEvaluators).where(and(eq(webhookDestinationEvaluators.tenantId, scopes.tenantId), eq(webhookDestinationEvaluators.projectId, scopes.projectId), eq(webhookDestinationEvaluators.webhookDestinationId, webhookDestinationId)));
	if (evaluatorIds.length > 0) await db.insert(webhookDestinationEvaluators).values(evaluatorIds.map((evaluatorId) => ({
		id: generateId(),
		tenantId: scopes.tenantId,
		projectId: scopes.projectId,
		webhookDestinationId,
		evaluatorId
	})));
};

//#endregion
export { createWebhookDestination, deleteWebhookDestination, getWebhookDestinationAgentIds, getWebhookDestinationById, getWebhookDestinationEvaluatorIds, listEnabledWebhookDestinations, listWebhookDestinationsPaginated, setWebhookDestinationAgentIds, setWebhookDestinationEvaluatorIds, updateWebhookDestination };