import { definePlugin } from "../../utils/plugin-utils";
import { createPaginatedPluginMethod } from "../../utils/plugin-utils";
import { ListConnectionsQuerySchema } from "./schemas";
import { splitVersionedKey, resolveConnectionId, transformConnectionItem, } from "../../utils/domain-utils";
import { extractCursor } from "../../utils/function-utils";
import { DEFAULT_PAGE_SIZE } from "../../constants";
import { appKeyResolver } from "../../resolvers";
import { ConnectionItemSchema } from "../../schemas/Connection";
import { ZapierValidationError } from "../../types/errors";
import { setMethodMetadata } from "../../utils/telemetry-context";
export const listConnectionsPlugin = definePlugin((sdk) => createPaginatedPluginMethod(sdk, {
    name: "listConnections",
    categories: ["connection"],
    type: "list",
    itemType: "Connection",
    inputSchema: ListConnectionsQuerySchema,
    outputSchema: ConnectionItemSchema,
    defaultPageSize: DEFAULT_PAGE_SIZE,
    resolvers: { app: appKeyResolver },
    handler: async ({ sdk, options }) => {
        if (options.includeShared) {
            await sdk.context.checkCapability("canIncludeSharedConnections");
        }
        const { api, getVersionedImplementationId } = sdk.context;
        const searchParams = {};
        if (options.pageSize !== undefined) {
            searchParams.page_size = options.pageSize.toString();
        }
        const appKey = options.app ?? options.appKey;
        if (appKey) {
            const implementationId = await getVersionedImplementationId(appKey);
            if (implementationId) {
                setMethodMetadata({ selectedApi: implementationId });
                const [versionlessSelectedApi] = splitVersionedKey(implementationId);
                searchParams.app_key = versionlessSelectedApi;
            }
            else {
                // If we can't resolve via manifest, pass the raw appKey and let the API handle it
                searchParams.app_key = appKey;
            }
        }
        // Resolve connection references (names from map, or direct IDs).
        // - connections: resolve names from map, fall back to direct IDs.
        // - connectionIds/authenticationIds: use directly (legacy).
        const connectionRefs = options.connections;
        const legacyConnectionIds = options.connectionIds ?? options.authenticationIds;
        if (connectionRefs && connectionRefs.length > 0) {
            const resolvedIds = await Promise.all(connectionRefs.map((ref) => resolveConnectionId({
                connection: ref,
                resolveConnection: sdk.context.resolveConnection,
            })));
            searchParams.connection_ids = resolvedIds
                .filter((id) => id != null)
                .join(",");
        }
        else if (legacyConnectionIds && legacyConnectionIds.length > 0) {
            searchParams.connection_ids = legacyConnectionIds.join(",");
        }
        if (options.search) {
            searchParams.search = options.search;
        }
        if (options.title) {
            searchParams.title = options.title;
        }
        const accountId = options.account ?? options.accountId;
        if (accountId) {
            searchParams.account_id = accountId;
        }
        if (options.owner && options.owner !== "me" && !options.includeShared) {
            throw new ZapierValidationError('The "owner" option requires "includeShared" to be true. Without includeShared, only your own connections are returned.');
        }
        const owner = options.includeShared ? options.owner : "me";
        if (owner) {
            searchParams.owner = owner;
        }
        // isExpired takes priority when explicitly set. Otherwise expired
        // defaults to false: only non-expired connections returned unless
        // caller opts in.
        if (options.isExpired !== undefined) {
            searchParams.is_expired = options.isExpired.toString();
        }
        else {
            searchParams.is_expired = (options.expired ?? false).toString();
        }
        if (options.cursor) {
            searchParams.offset = options.cursor;
        }
        const response = await api.get("/api/v0/connections", { searchParams, authRequired: true });
        return {
            ...response,
            data: response.data.map(transformConnectionItem),
        };
    },
    extractCursor: (response) => extractCursor(response.links),
}));
