import { definePlugin } from "../../utils/plugin-utils";
import { createPaginatedPluginMethod } from "../../utils/plugin-utils";
import { ListActionInputFieldChoicesInputSchema, InputFieldChoiceItemSchema, } from "./schemas";
import { ZapierApiError, ZapierConfigurationError } from "../../types/errors";
import { DEFAULT_PAGE_SIZE } from "../../constants";
import { appKeyResolver, actionTypeResolver, actionKeyResolver, connectionIdResolver, inputFieldKeyResolver, inputsAllOptionalResolver, } from "../../resolvers";
import { fetchImplementationNeeds, fetchImplementationChoices, } from "../../services/implementations";
import { resolveConnectionId } from "../../utils/domain-utils";
import { setMethodMetadata } from "../../utils/telemetry-context";
function transformNeedChoicesToInputFieldChoiceItem(choice) {
    return {
        key: choice.key,
        label: choice.label,
        sample: choice.sample,
        value: choice.value,
    };
}
export const listActionInputFieldChoicesPlugin = definePlugin((sdk) => createPaginatedPluginMethod(sdk, {
    name: "listActionInputFieldChoices",
    categories: ["action"],
    type: "list",
    itemType: "InputFieldChoice",
    inputSchema: ListActionInputFieldChoicesInputSchema,
    outputSchema: InputFieldChoiceItemSchema,
    defaultPageSize: DEFAULT_PAGE_SIZE,
    resolvers: {
        app: appKeyResolver,
        actionType: actionTypeResolver,
        action: actionKeyResolver,
        connection: connectionIdResolver,
        inputField: inputFieldKeyResolver,
        inputs: inputsAllOptionalResolver,
    },
    handler: async ({ sdk, options, }) => {
        const { api, getVersionedImplementationId } = sdk.context;
        const appKey = "app" in options ? options.app : options.appKey;
        const actionKey = "action" in options ? options.action : options.actionKey;
        const inputFieldKey = "inputField" in options ? options.inputField : options.inputFieldKey;
        const { actionType, connection, connectionId, authenticationId, inputs, page, cursor, } = options;
        const resolvedConnectionId = await resolveConnectionId({
            connection,
            connectionId,
            authenticationId,
            resolveConnection: sdk.context.resolveConnection,
        });
        const selectedApi = await getVersionedImplementationId(appKey);
        if (!selectedApi) {
            throw new ZapierConfigurationError("No current_implementation_id found for app", { configType: "current_implementation_id" });
        }
        setMethodMetadata({
            selectedApi,
            operationType: actionType,
            operationKey: actionKey,
        });
        const { data: action } = await sdk.getAction({
            app: appKey,
            actionType,
            action: actionKey,
        });
        // Static choices via implementation needs.
        const needsData = await fetchImplementationNeeds({
            api,
            selectedApi,
            action: action.key,
            actionType,
            connectionId: resolvedConnectionId ?? null,
            inputs,
        });
        const targetNeed = needsData.needs?.find((need) => need.key === inputFieldKey);
        if (targetNeed?.choices && targetNeed.choices.length > 0) {
            return {
                data: targetNeed.choices.map(transformNeedChoicesToInputFieldChoiceItem),
            };
        }
        if (!action.id) {
            throw new ZapierApiError(`Action ${actionKey} does not have an ID - cannot retrieve input field choices`);
        }
        // Use cursor as page number if available; else use explicit page; else 0.
        const requestPage = cursor ? parseInt(cursor, 10) : (page ?? 0);
        const choicesData = await fetchImplementationChoices({
            api,
            actionId: action.id,
            inputFieldId: inputFieldKey,
            connectionId: resolvedConnectionId ?? null,
            inputs,
            page: requestPage,
        });
        const choices = (choicesData.choices || []).map(transformNeedChoicesToInputFieldChoiceItem);
        let nextCursor;
        if (choicesData.next_page != null) {
            nextCursor = choicesData.next_page.toString();
        }
        else if (choicesData.links?.next) {
            // External actions: extract `page` query param from links.next.
            try {
                const nextUrl = new URL(choicesData.links.next);
                const nextPage = nextUrl.searchParams.get("page");
                if (nextPage) {
                    nextCursor = nextPage;
                }
            }
            catch {
                // Malformed URL; fall through to undefined.
            }
        }
        return { data: choices, nextCursor };
    },
}));
