export interface ErrorWithCode<Code extends string = string> extends Error {
    code: Code;
}
export type ActionType = 'local' | 'remote';
export type ActionVisibility = 'public' | 'internal';
export type ActionResult = 'success' | 'error';
export interface BrowserContext {
    origin: string;
    pathname: string;
    userAgent?: string;
    platform?: string;
    language?: string;
    timeZone?: string;
}
export interface ActionEventContext {
    sdkInitId: string;
    sdkVersion: string;
    sdkKey: string;
    journeyToken: string;
    journeyApplicationToken?: string;
    entityToken?: string;
}
export interface CanonicalActionEvent {
    requestId: string;
    qualifiedAction: string;
    actionType: ActionType;
    visibility: ActionVisibility;
    result: ActionResult;
    startedAtMs: number;
    endedAtMs: number;
    durationMs: number;
    errorCode?: string;
    sdkInitId: string;
    sdkVersion: string;
    sdkKey: string;
    journeyToken: string;
    journeyApplicationToken?: string;
    entityToken?: string;
    browserContext: BrowserContext;
}
export interface ActionRuntimeRetryPolicy {
    maxAttempts: number;
    onStatus?: number[];
    onNetworkError?: boolean;
    backoffMs?: number;
    jitter?: boolean;
}
export interface RemoteActionOptions {
    /**
     * Retry policy applied by the action runtime (inside the iframe), not by the
     * SDK side. Set per-action when the default isn't right for this action; see
     * the action runtime sub-page in docs for enforcement details and defaults.
     *
     * For handler-form remote actions, this policy applies to every `ctx.emit`
     * inside the handler (the handler itself runs locally and isn't retried).
     */
    retry?: ActionRuntimeRetryPolicy;
    /**
     * Overrides the SDK-side call timeout for this action. Defaults to 10s if
     * unset. Set this when your retry policy or per-attempt budget can legitimately
     * exceed the default; otherwise the SDK rejects the call before the runtime is
     * done.
     *
     * For handler-form remote actions, this applies to each nested `ctx.emit`
     * (the handler itself runs locally and has no SDK-side timeout).
     */
    timeoutMs?: number;
}
export interface RemoteCallContext {
    visibility: ActionVisibility;
    retry?: ActionRuntimeRetryPolicy;
    timeoutMs?: number;
}
export type RemoteActionMethod<Req = unknown, Res = unknown> = (payload: Req) => Promise<Res>;
export type ActionMethod<Args extends unknown[] = unknown[], Res = unknown> = (...args: Args) => Res;
export type ActionCallable = ActionMethod<unknown[], unknown>;
/**
 * Phantom type marker: `actionVisibilityTag` is type-only and never set at
 * runtime. It exists so `PublicActionKeys` can narrow a namespace's method
 * map to just the public methods at compile time.
 */
export interface ActionVisibilityMarker<V extends ActionVisibility> {
    actionVisibilityTag?: V;
}
export type TaggedActionMethod<Fn, V extends ActionVisibility> = Fn & ActionVisibilityMarker<V>;
export type ActionNamespaceMethods = Record<string, ActionCallable>;
export type ActionNamespaces = Record<string, ActionNamespaceMethods>;
export interface RemoteActionHandlerContext {
    emit: <Req = unknown, Res = unknown>(action: string, payload: Req) => Promise<Res>;
}
export type RemoteActionHandler<Req, Res> = (ctx: RemoteActionHandlerContext, payload: Req) => Promise<Res> | Res;
export interface ActionFactory<V extends ActionVisibility> {
    <Args extends unknown[] = unknown[], Res = unknown>(handler: ActionMethod<Args, Res>): TaggedActionMethod<ActionMethod<Args, Res>, V>;
}
export interface RemoteActionFactory<V extends ActionVisibility> {
    <Req = unknown, Res = unknown>(action: string, options?: RemoteActionOptions): TaggedActionMethod<RemoteActionMethod<Req, Res>, V>;
    <Req = unknown, Res = unknown>(handler: RemoteActionHandler<Req, Res>, options?: RemoteActionOptions): TaggedActionMethod<RemoteActionMethod<Req, Res>, V>;
}
export interface ActionDefineHelpers {
    publicLocalAction: ActionFactory<'public'>;
    internalLocalAction: ActionFactory<'internal'>;
    publicRemoteAction: RemoteActionFactory<'public'>;
    internalRemoteAction: RemoteActionFactory<'internal'>;
}
export type ActionRuntimeTransportContext = ActionEventContext;
export interface ActionRuntimeCallArgs<Req = unknown> {
    qualifiedAction: string;
    payload: Req;
    callContext: RemoteCallContext;
}
export interface ActionRuntimeTransport {
    prepareIframe: () => Promise<void>;
    call: <Req = unknown, Res = unknown>(args: ActionRuntimeCallArgs<Req>) => Promise<Res>;
    destroy: () => Promise<void>;
}
export interface CreateActionRuntimeTransportOptions {
    iframeUrl: string;
    context: ActionRuntimeTransportContext;
}
export type PublicActionKeys<Methods extends Record<string, unknown>> = {
    [K in keyof Methods]: Methods[K] extends ActionVisibilityMarker<'public'> ? K : never;
}[keyof Methods];
export type PublicActionNamespace<Methods extends Record<string, unknown>> = Pick<Methods, PublicActionKeys<Methods>>;
