/**
 * Public + protocol types for `@audin.ai/operator-sdk`.
 *
 * Naming is deliberately neutral: this SDK is shipped to partners and never
 * names the underlying telephony or AI providers. It speaks only of "calls",
 * "phone numbers" and "audio".
 */
/**
 * The token your application's backend returns for a softphone session.
 *
 * Your backend calls the Audin REST API `POST /operator-sessions/token`
 * (authenticated with your Account API Key — which NEVER leaves your server)
 * and returns at least the `token` here. The SDK presents this token to the
 * Audin WebSockets; it is short-lived (~1h) and the SDK requests a fresh one
 * via {@link AudinOperatorConfig.getToken} whenever it (re)connects.
 */
export interface OperatorSessionToken {
    /** Short-lived session JWT the SDK presents to the Audin WebSockets. */
    token: string;
    /** Optional ISO-8601 expiry. If provided, the SDK refreshes ahead of it. */
    expiresAt?: string;
}
/** Async provider of a fresh {@link OperatorSessionToken}. */
export type GetTokenFn = () => Promise<OperatorSessionToken>;
/**
 * A phone number the operator's account owns and may go online on / dial from.
 * Returned by {@link AudinOperator.listPhoneNumbers}.
 */
export interface OperatorPhoneNumber {
    /** Stable identifier — pass to `goOnline([...])`. */
    id: string;
    /** E.164 number — present as `callerId` when dialling. */
    phoneNumber: string;
    /** Human label, when set. */
    displayName: string | null;
}
/** Direction of a call from the operator's point of view. */
export type CallDirection = "inbound" | "outbound";
/** Lifecycle state of a {@link OperatorCall}. */
export type CallState = "ringing" | "connecting" | "active" | "ended";
/** Why a call ended — surfaced on the `callEnded` event. */
export type CallEndReason = "hangup" | "remote_hangup" | "taken_by_other" | "rejected" | "no_answer" | "failed" | "offline";
/**
 * Configuration for {@link AudinOperator}.
 */
export interface AudinOperatorConfig {
    /**
     * Base URL of the Audin operator service, e.g. `https://core.<audin-host>`.
     * `http(s)` is accepted and upgraded to the matching `ws(s)` scheme
     * internally. Trailing slashes are tolerated.
     */
    coreUrl: string;
    /**
     * Returns a fresh session token. Called on initial connect AND on every
     * reconnect, so always fetch a NEW token (do not cache an expired one).
     * This is the single seam through which credentials enter the SDK — the
     * Account API Key stays on your backend.
     */
    getToken: GetTokenFn;
    /**
     * Heartbeat interval (ms) for the presence connection. Defaults to 25000.
     * The server reaps connections idle for ~90s, so keep this well under that.
     */
    heartbeatIntervalMs?: number;
    /**
     * Reconnect backoff schedule (ms) for the presence connection. The SDK
     * walks this array on consecutive failures and stays on the last value
     * thereafter. Defaults to `[1000, 2000, 5000, 10000, 30000]`.
     */
    reconnectBackoffMs?: number[];
    /**
     * Constraints passed to `getUserMedia({ audio })` for microphone capture.
     * Defaults enable echo cancellation, noise suppression and auto gain.
     */
    audioConstraints?: MediaTrackConstraints;
    /** Optional sink for SDK diagnostics. Defaults to `console`. */
    logger?: OperatorLogger;
}
/** Minimal logger surface the SDK writes to (defaults to `console`). */
export interface OperatorLogger {
    debug(...args: unknown[]): void;
    info(...args: unknown[]): void;
    warn(...args: unknown[]): void;
    error(...args: unknown[]): void;
}
/** Connection state of the presence channel. */
export type PresenceState = "offline" | "connecting" | "online" | "reconnecting";
/**
 * Events emitted by {@link AudinOperator}. Subscribe with `op.on(name, cb)`.
 */
export interface AudinOperatorEventMap {
    /** Presence channel state changed. */
    presenceStateChanged: PresenceState;
    /** The set of phone numbers the operator is online on was (re)confirmed. */
    availabilityChanged: {
        accepted: string[];
        rejected: string[];
    };
    /** An inbound call is ringing. Call `call.accept()` or `call.reject()`. */
    incomingCall: OperatorCall;
    /** A call's audio is being established (after accept / dial). */
    callStarted: OperatorCall;
    /** A call ended. Inspect `call.endReason`. */
    callEnded: OperatorCall;
    /** A non-fatal error. The SDK keeps running where it can. */
    error: OperatorError;
}
/** Names of the events in {@link AudinOperatorEventMap}. */
export type AudinOperatorEventName = keyof AudinOperatorEventMap;
/** Listener signature for a given event. */
export type AudinOperatorListener<K extends AudinOperatorEventName> = (payload: AudinOperatorEventMap[K]) => void;
/** Structured error surfaced on the `error` event. */
export interface OperatorError {
    /** Stable machine code, e.g. `MIC_PERMISSION_DENIED`, `WS_ERROR`. */
    code: string;
    /** Human-readable description. */
    message: string;
    /** Original error / server payload, if any. */
    cause?: unknown;
}
/** Options for {@link AudinOperator.dial}. */
export interface DialOptions {
    /**
     * Caller ID to present — MUST be a phone number your account owns and that
     * is active. Required by the platform for outbound calls.
     */
    callerId: string;
}
/**
 * Handle to a single call. Obtained from the `incomingCall` / `callStarted`
 * events or returned by {@link AudinOperator.dial}.
 */
export interface OperatorCall {
    /** Platform call identifier. */
    readonly callSid: string;
    /** inbound | outbound. */
    readonly direction: CallDirection;
    /** Remote party number (E.164) when known. */
    readonly from?: string;
    /** Local/called number (E.164) when known. */
    readonly to?: string;
    /** Current lifecycle state. */
    readonly state: CallState;
    /** Populated once `state === "ended"`. */
    readonly endReason?: CallEndReason;
    /** Answer an inbound offer. No-op if not ringing. */
    accept(): void;
    /** Decline an inbound offer. No-op if not ringing. */
    reject(): void;
    /** Mute / unmute the operator microphone toward the far end. */
    mute(on: boolean): void;
    /** Whether the operator microphone is currently muted. */
    readonly muted: boolean;
    /**
     * Send a DTMF digit (`0-9`, `*`, `#`).
     *
     * NOT YET SUPPORTED END-TO-END. The digit is validated and emitted as a
     * control message on the call channel, but the server does not yet forward
     * the tones onto the telephone network — so today this is effectively a
     * functional no-op for the far end. The method is kept (and the wire message
     * remains valid) so that enabling it server-side in a future version requires
     * no SDK change, but do NOT rely on the remote party hearing the tones yet.
     */
    sendDtmf(digit: string): void;
    /** Hang up the call. */
    hangup(): void;
}
