import { z } from "zod";
import { TriggerInboxPropertySchema, LeaseSecondsPropertySchema, } from "../../../types/properties";
import { ZapierSignal } from "../../../types/signals";
/**
 * Signal an `onMessage` callback can throw to release the current
 * message back to the inbox immediately (status returns to
 * `available`) rather than leaving it leased until the lease
 * timeout. The actual release call is deferred to the end of the
 * drain so the same drain doesn't immediately re-lease it.
 *
 * Always triggers release regardless of `releaseOnError`.
 */
export class ZapierReleaseTriggerMessageSignal extends ZapierSignal {
    constructor() {
        super(...arguments);
        this.name = "ZapierReleaseTriggerMessageSignal";
        this.code = "ZAPIER_RELEASE_TRIGGER_MESSAGE_SIGNAL";
    }
}
/**
 * Signal an `onMessage` callback can throw to stop the drain after
 * the current batch — no further leases, no further callbacks. The
 * triggering message gets the same release-or-leave treatment as any
 * thrown error (per `releaseOnError`). Other in-flight messages in
 * the same batch finish normally before the command returns.
 * Already-leased-but-not-yet-started messages are released so
 * they're available for re-lease.
 */
export class ZapierAbortDrainSignal extends ZapierSignal {
    constructor() {
        super(...arguments);
        this.name = "ZapierAbortDrainSignal";
        this.code = "ZAPIER_ABORT_DRAIN_SIGNAL";
    }
}
/**
 * Source-level options shared by `drainTriggerInbox` and
 * `watchTriggerInbox`. Both methods are eager commands that lease,
 * process via `onMessage`, and return when done.
 *
 * `onMessage` is required. There's no identity default, since "lease
 * and ack everything in this inbox" is a footgun that destroys data
 * on a casual call. Subprocess-style handlers (spawn a binary per
 * message, pipe message JSON to stdin) live as CLI-only flags
 * (`--exec`, `--exec-shell`); the CLI wraps them into an `onMessage`
 * before calling the SDK. Programmatic SDK callers that want the
 * same behavior compose their own `onMessage` around `child_process`.
 */
const TriggerInboxCommandBaseSchema = z.object({
    inbox: TriggerInboxPropertySchema,
    onMessage: z
        .function()
        .optional()
        .meta({ exampleRequired: true })
        .describe("Per-message handler. Resolves to ack; rejects to release-or-leave per `releaseOnError`. Throw `ZapierReleaseTriggerMessageSignal` to release explicitly, or `ZapierAbortDrainSignal` to stop after the current batch."),
    concurrency: z
        .number()
        .int()
        .min(1)
        .optional()
        .describe("Per-message handler workers running in parallel. Defaults to `leaseLimit`, or 1 if neither is set."),
    leaseLimit: z
        .number()
        .int()
        .min(1)
        .max(100)
        .optional()
        .describe("Per-lease HTTP batch size. Defaults to `concurrency`, or 1 if neither is set."),
    leaseSeconds: LeaseSecondsPropertySchema.optional(),
    releaseOnError: z
        .boolean()
        .optional()
        .describe("If true, errors release the message when the drain finishes. If false (default), errors leave it leased until the lease timeout. `ZapierReleaseTriggerMessageSignal` always releases regardless."),
    continueOnError: z
        .boolean()
        .optional()
        .describe("If false (default, fail-fast), the first handler error rejects and stops the drain. If true, handler errors are observed via `onError` and the drain continues. SDK-level errors (lease / ack / release) reject regardless."),
    onError: z
        .function()
        .optional()
        .describe("Per-message error observer for `continueOnError: true`. Called with the failure and the message; control-flow signals are filtered out. Throws from `onError` are swallowed."),
    signal: z
        .custom((v) => v instanceof AbortSignal)
        .optional()
        .describe("Abort signal. Aborting cancels in-flight HTTP, releases unprocessed messages, and resolves cleanly. Errors during shutdown still reject."),
});
export const DrainTriggerInboxSchema = TriggerInboxCommandBaseSchema.extend({
    maxMessages: z
        .number()
        .int()
        .min(1)
        .optional()
        .describe("Cap total messages drained. Defaults to draining the inbox until empty."),
}).describe("Drain an existing trigger inbox: lease currently-available messages and process them via onMessage. Returns when the inbox is empty, maxMessages is reached, the abort signal fires, or a fatal error rejects.");
export const WatchTriggerInboxSchema = TriggerInboxCommandBaseSchema.extend({
    maxDrainIntervalSeconds: z
        .number()
        .int()
        .min(1)
        .optional()
        .describe("Maximum seconds between empty-inbox poll attempts (default: 60). Caps the back-off cadence."),
}).describe("Continuously consume a trigger inbox: drain currently-available messages, then poll with backoff for new arrivals, until aborted. Stop via the `signal` AbortSignal or by throwing `ZapierAbortDrainSignal` from a handler. Resolves cleanly on abort; rejects on a fatal error or a fail-fast handler error.");
