import { agentIntegrations, agents } from "@rudderhq/db";
import { createAgentIntegrationSchema } from "@rudderhq/shared";
import { and, desc, eq } from "drizzle-orm";
import { conflict, notFound, unprocessable } from "../../errors.js";
import { secretService } from "../secrets.js";
export function summarizeAgentIntegration(row) {
    const { appCredentialSecretId: _appCredentialSecretId, ...rest } = row;
    return {
        ...rest,
        provider: rest.provider,
        status: rest.status,
        transport: rest.transport,
        providerRegion: rest.providerRegion,
        hasCredentialSecret: Boolean(_appCredentialSecretId),
    };
}
export function agentIntegrationService(db) {
    const secrets = secretService(db);
    async function assertAgentInOrg(orgId, agentId) {
        const agent = await db
            .select({ id: agents.id, orgId: agents.orgId })
            .from(agents)
            .where(eq(agents.id, agentId))
            .then((rows) => rows[0] ?? null);
        if (!agent)
            throw notFound("Agent not found");
        if (agent.orgId !== orgId)
            throw unprocessable("Agent integration must belong to same organization");
    }
    async function assertSecretInOrg(orgId, secretId) {
        const secret = await secrets.getById(secretId);
        if (!secret)
            throw notFound("Integration credential secret not found");
        if (secret.orgId !== orgId) {
            throw unprocessable("Integration credential secret must belong to same organization");
        }
    }
    return {
        listForAgent: (orgId, agentId) => db
            .select()
            .from(agentIntegrations)
            .where(and(eq(agentIntegrations.orgId, orgId), eq(agentIntegrations.agentId, agentId)))
            .orderBy(desc(agentIntegrations.updatedAt))
            .then((rows) => rows.map(summarizeAgentIntegration)),
        getAgentProvider: (orgId, agentId, provider) => db
            .select()
            .from(agentIntegrations)
            .where(and(eq(agentIntegrations.orgId, orgId), eq(agentIntegrations.agentId, agentId), eq(agentIntegrations.provider, provider)))
            .then((rows) => rows[0] ?? null),
        create: async (orgId, input) => {
            const parsed = createAgentIntegrationSchema.parse(input);
            await assertAgentInOrg(orgId, parsed.agentId);
            await assertSecretInOrg(orgId, parsed.appCredentialSecretId);
            const existing = await db
                .select()
                .from(agentIntegrations)
                .where(and(eq(agentIntegrations.orgId, orgId), eq(agentIntegrations.agentId, parsed.agentId), eq(agentIntegrations.provider, parsed.provider)))
                .then((rows) => rows[0] ?? null);
            if (existing && existing.status === "active") {
                throw conflict("Agent already has an active integration for this provider");
            }
            if (existing) {
                return db
                    .update(agentIntegrations)
                    .set({
                    status: "active",
                    transport: parsed.transport,
                    providerRegion: parsed.providerRegion,
                    appCredentialSecretId: parsed.appCredentialSecretId,
                    externalAppId: parsed.externalAppId,
                    externalBotOpenId: parsed.externalBotOpenId ?? null,
                    externalTenantKey: parsed.externalTenantKey ?? null,
                    installerUserId: parsed.installerUserId ?? null,
                    manageUrl: parsed.manageUrl ?? null,
                    installedAt: new Date(),
                    revokedAt: null,
                    updatedAt: new Date(),
                })
                    .where(eq(agentIntegrations.id, existing.id))
                    .returning()
                    .then((rows) => rows[0]);
            }
            return db
                .insert(agentIntegrations)
                .values({
                orgId,
                agentId: parsed.agentId,
                provider: parsed.provider,
                transport: parsed.transport,
                providerRegion: parsed.providerRegion,
                appCredentialSecretId: parsed.appCredentialSecretId,
                externalAppId: parsed.externalAppId,
                externalBotOpenId: parsed.externalBotOpenId ?? null,
                externalTenantKey: parsed.externalTenantKey ?? null,
                installerUserId: parsed.installerUserId ?? null,
                manageUrl: parsed.manageUrl ?? null,
            })
                .returning()
                .then((rows) => rows[0]);
        },
        markErrorForAgent: async (orgId, agentId, integrationId) => db
            .update(agentIntegrations)
            .set({
            status: "error",
            updatedAt: new Date(),
        })
            .where(and(eq(agentIntegrations.orgId, orgId), eq(agentIntegrations.agentId, agentId), eq(agentIntegrations.id, integrationId)))
            .returning()
            .then((rows) => rows[0] ?? null),
        revoke: async (orgId, integrationId) => db
            .update(agentIntegrations)
            .set({
            status: "revoked",
            revokedAt: new Date(),
            updatedAt: new Date(),
        })
            .where(and(eq(agentIntegrations.orgId, orgId), eq(agentIntegrations.id, integrationId)))
            .returning()
            .then((rows) => rows[0] ?? null),
        revokeForAgent: async (orgId, agentId, integrationId) => db
            .update(agentIntegrations)
            .set({
            status: "revoked",
            revokedAt: new Date(),
            updatedAt: new Date(),
        })
            .where(and(eq(agentIntegrations.orgId, orgId), eq(agentIntegrations.agentId, agentId), eq(agentIntegrations.id, integrationId)))
            .returning()
            .then((rows) => rows[0] ?? null),
    };
}
//# sourceMappingURL=agent-integrations.js.map