import type { Output, SignalValue, StatusJson } from "@mochabug/adapt-core";
import type { AdaptTheme } from "./theme.js";
export type { Output, SignalValue, StatusJson } from "@mochabug/adapt-core";
export type { AdaptTheme } from "./theme.js";
/**
 * Options for session persistence across page refreshes.
 */
export interface PersistOptions {
    /** Storage type: 'session' (default) uses sessionStorage, 'local' uses localStorage. */
    storage?: "session" | "local";
    /** Max TTL in seconds (default: 3600). Capped by the session's own expiresAt. */
    ttl?: number;
    /** Custom storage key suffix to distinguish multiple embeds of the same automation. */
    key?: string;
}
/**
 * Discriminated union for fork display configuration.
 *
 * - `"side-by-side"`: Shows main and fork iframes side by side
 * - `"dialog"`: Shows fork in a floating group
 */
export type ForkDisplay = {
    mode: "side-by-side";
    split?: number;
} | {
    mode: "dialog";
};
/**
 * Custom label overrides for the Cap.js widget.
 * All fields are optional — unspecified labels use Cap.js defaults.
 *
 * These map to `data-cap-i18n-*` attributes on the underlying `<cap-widget>`.
 *
 * @example
 * ```typescript
 * i18n: {
 *   initialState: "Verify you're human",
 *   verifyingLabel: "Checking...",
 *   solvedLabel: "Verified!",
 *   errorLabel: "Failed"
 * }
 * ```
 */
export interface CapWidgetI18n {
    /** Text shown while the proof-of-work is being solved. Default: `"Verifying..."` */
    verifyingLabel?: string;
    /** Text shown before the user clicks the checkbox. Default: `"Verify you're human"` */
    initialState?: string;
    /** Text shown after a successful solve. Default: `"You're a human"` */
    solvedLabel?: string;
    /** Text shown when solving fails. Default: `"Error. Try again."` */
    errorLabel?: string;
    /** Text shown for the blocked-user troubleshooting link. Default: `"Troubleshoot"` */
    troubleshootingLabel?: string;
    /** Text shown when WebAssembly is unavailable. */
    wasmDisabled?: string;
    /** ARIA label for the initial interactive state. */
    verifyAriaLabel?: string;
    /** ARIA label while verification is running. */
    verifyingAriaLabel?: string;
    /** ARIA label after successful verification. */
    verifiedAriaLabel?: string;
    /** Validation text when the widget is required in a form. */
    requiredLabel?: string;
    /** ARIA label when an error occurs. */
    errorAriaLabel?: string;
}
/**
 * Options for the Cap.js widget when used via `AdaptWebClient` with `requiresChallenge: true`.
 *
 * @example
 * ```typescript
 * capWidgetOptions: {
 *   workerCount: 4,
 *   i18n: { initialState: "Click to verify" }
 * }
 * ```
 */
export interface CapWidgetOptions {
    /** Custom text labels for the widget. */
    i18n?: CapWidgetI18n;
    /** Number of Web Workers for solving. @default navigator.hardwareConcurrency || 8 */
    workerCount?: number;
    /** Name of the hidden token input generated by Cap.js. @default `"cap-token"` */
    hiddenFieldName?: string;
    /** Custom URL for Cap.js's troubleshooting link when instrumentation blocks a user. */
    troubleshootingUrl?: string;
    /** Disable Cap.js haptic feedback for this widget. */
    disableHaptics?: boolean;
}
/**
 * Challenge information returned from createChallenge
 */
export interface ChallengeInfo {
    /** Number of challenges to solve */
    count: number;
    /** Salt size in bytes */
    size: number;
    /** Difficulty target (hex prefix length) */
    difficulty: number;
    /** When the challenge expires */
    expires: Date;
    /** Hex-encoded seed for Cap.js PRNG derivation (64 chars) */
    token: string;
    /** Encrypted verification token for server */
    verificationToken: string;
    /** Optional Cap.js instrumentation payload to execute before redeeming */
    instrumentation?: string;
}
export interface RedeemChallengeOptions {
    /** Successful Cap.js instrumentation result sent as `instr` by the widget */
    instrumentation?: Record<string, unknown>;
    /** True when Cap.js reports that instrumentation detected an automated browser */
    instrumentationBlocked?: boolean;
    /** True when Cap.js reports that instrumentation timed out */
    instrumentationTimeout?: boolean;
}
/**
 * Redeemed challenge returned from redeemChallenge
 */
export interface RedeemedChallenge {
    /** The redeemed token to pass to startSession/runSession */
    token: string;
    /** When the redeemed token expires */
    expires: Date;
}
/**
 * Configuration options for AdaptWebClient
 *
 * @example
 * ```typescript
 * // Basic usage
 * const client = new AdaptWebClient({
 *   container: 'my-container',
 *   automationId: 'automation-123',
 *   authToken: 'optional-auth-token'
 * });
 *
 * // With fork display options
 * const client = new AdaptWebClient({
 *   container: 'my-container',
 *   automationId: 'automation-123',
 *   forkDisplay: { mode: 'dialog' }
 * });
 *
 * // With custom styling
 * const client = new AdaptWebClient({
 *   container: 'my-container',
 *   automationId: 'automation-123',
 *   classNames: {
 *     root: 'my-custom-class',
 *     iframe: 'my-iframe-class'
 *   },
 *   styles: {
 *     height: '600px'
 *   }
 * });
 * ```
 */
export interface AdaptWebClientOptions {
    /**
     * HTML element or ID of the element where the client will render.
     * The element must exist in the DOM before creating the client.
     *
     * @example
     * ```html
     * <div id="my-container"></div>
     * ```
     * ```typescript
     * container: 'my-container'
     * // or
     * container: document.getElementById('my-container')
     * ```
     */
    container: string | HTMLElement;
    /**
     * Automation ID to connect to.
     * This ID is provided by the Adapt automation platform.
     */
    automationId: string;
    /**
     * Pre-created session token from server-side session creation.
     * When provided, skips client-side startSession/inheritSession calls entirely.
     *
     * Use this for SSR frameworks (Next.js, Nuxt, etc.) where the authToken
     * should remain on the server for security.
     *
     * @example
     * ```typescript
     * // Server-side (e.g., Next.js API route or server component)
     * const { token } = await startSession({ id: 'automation-123' }, authToken);
     *
     * // Client-side
     * const client = new AdaptWebClient({
     *   container: 'my-container',
     *   automationId: 'automation-123',
     *   sessionToken: token  // Use pre-created session
     * });
     * ```
     */
    sessionToken?: string;
    /**
     * Authentication token for starting a new session client-side.
     * Use this for SPA applications where the token is available on the frontend.
     *
     * Ignored if sessionToken is provided.
     */
    authToken?: string;
    /**
     * The transmitter to start from (optional).
     * Use this when your automation has multiple transmitters and you want to
     * specify which one to start from. Defaults to the first transmitter if not specified.
     *
     * Ignored if sessionToken is provided.
     *
     * @example
     * ```typescript
     * transmitter: 'my-transmitter-name'
     * ```
     */
    transmitter?: string;
    /**
     * Initial signals to pass to the transmitter.
     * The signals must align with the transmitter's JTD schema.
     *
     * Ignored if sessionToken is provided.
     *
     * @example
     * ```typescript
     * signals: {
     *   'input': { mimeType: 'text/plain', data: btoa('Hello World') }
     * }
     * ```
     */
    signals?: {
        [key: string]: SignalValue;
    };
    /**
     * Pre-solved challenge token for automations requiring proof-of-work.
     * When provided, skips the Cap.js widget and uses this token directly.
     *
     * Ignored if sessionToken is provided.
     *
     * @example
     * ```typescript
     * // From server-side pre-solving
     * challengeToken: presolvedToken
     * ```
     */
    challengeToken?: string;
    /**
     * Show a Cap.js proof-of-work widget before starting the session.
     * The widget handles challenge creation, solving, and redemption automatically.
     * It is centered inside the container and auto-removes after a successful solve.
     *
     * **Styling:** Customize via `--mb-adapt-cap-*` CSS variables on the `.mb-adapt` root.
     * Dark mode colors are applied automatically when `darkMode: true`.
     * Never use `::part()` selectors on the inner `<cap-widget>` — this breaks
     * Cap.js's Shadow DOM animations (checkbox, spinner, label transitions).
     *
     * Ignored when `sessionToken` or `challengeToken` is provided.
     *
     * @default false
     */
    requiresChallenge?: boolean;
    /**
     * Options for the Cap.js widget (labels and worker count).
     * Only used when `requiresChallenge` is `true`.
     *
     * @example
     * ```typescript
     * capWidgetOptions: {
     *   workerCount: 4,
     *   i18n: { initialState: "Verify you're human" }
     * }
     * ```
     */
    capWidgetOptions?: CapWidgetOptions;
    /**
     * Token to inherit an existing session.
     * When provided, calls inheritSession() instead of startSession().
     *
     * Ignored if sessionToken is provided.
     */
    inheritToken?: string;
    /**
     * Auto-parse inherit token from URL.
     * Token is removed from URL after parsing (via history.replaceState).
     * Takes precedence over inheritToken if token found in URL.
     *
     * @example
     * ```typescript
     * // Parse from hash: example.com#mb_session=xxx
     * inheritFrom: { hash: 'mb_session' }
     *
     * // Parse from query param: example.com?token=xxx
     * inheritFrom: { param: 'token' }
     * ```
     */
    inheritFrom?: {
        hash: string;
    } | {
        param: string;
    };
    /**
     * How to display fork URLs when automation creates sub-sessions.
     *
     * - `{ mode: "side-by-side", split?: number }`: Shows main and fork tabs docked to the right
     * - `{ mode: "dialog" }`: Shows fork tabs in a floating group
     *
     * @default { mode: "side-by-side" }
     * @example
     * ```typescript
     * // Side-by-side with 60/40 split
     * forkDisplay: { mode: "side-by-side", split: 60 }
     *
     * // Dialog (floating group)
     * forkDisplay: { mode: "dialog" }
     * ```
     */
    forkDisplay?: ForkDisplay;
    /**
     * Whether users can pop out / float panels.
     * When false, hides "Pop out" buttons and blocks user-initiated floating.
     * Does NOT affect `forkDisplay="dialog"` — that's the developer's chosen initial placement.
     *
     * @default true
     */
    allowFloating?: boolean;
    /**
     * Whether users can minimize panels (both docked and floating).
     * When false, hides "Minimize" buttons on docked group headers and floating toolbars.
     *
     * @default true
     */
    allowMinimize?: boolean;
    /**
     * Whether users can maximize panels (both docked and floating).
     * When false, hides "Maximize" buttons on docked group headers and floating toolbars.
     *
     * @default true
     */
    allowMaximize?: boolean;
    /**
     * Whether users can dock floating panels back to the main layout.
     * When false, hides "Dock" button on floating toolbar and minimized tabs.
     * Does NOT affect `forkDisplay="side-by-side"` — that's the developer's chosen initial placement.
     *
     * @default true
     */
    allowDocking?: boolean;
    /**
     * Whether users can create splits inside floating dialog overlays by dragging tabs.
     * When false, tabs dragged inside a floating overlay will merge into existing groups
     * instead of creating new split panes.
     *
     * @default true
     */
    allowDialogDocking?: boolean;
    /**
     * Auto-resize floating overlays based on iframe content height.
     * When true, floating overlays auto-resize based on iframe content (same mechanism
     * as `autoResizing` for the main panel, but targeting floating overlays).
     * Independent of the main `autoResizing` flag.
     *
     * @default false
     */
    floatingAutoResize?: boolean;
    /**
     * Enable dark mode. When changed, sends message to iframes via postMessage.
     *
     * @default false
     */
    darkMode?: boolean;
    /**
     * Auto-resize iframe height based on content.
     * When true, listens for resize messages from iframes and adjusts height.
     * Width remains at 100%.
     *
     * @default false
     */
    autoResizing?: boolean;
    /**
     * Prompt the user before closing panels that haven't completed, and before
     * navigating away from the page while a session is active.
     *
     * When true:
     * - Closing a fork tab that isn't marked complete shows a styled confirmation dialog.
     * - Navigating away (or refreshing) while a session is running triggers
     *   the browser's native `beforeunload` prompt.
     *
     * The confirmation dialog can be styled via CSS variables on `.mb-adapt`:
     *   --mb-adapt-confirm-overlay-bg, --mb-adapt-confirm-bg, --mb-adapt-confirm-text,
     *   --mb-adapt-confirm-btn-bg, --mb-adapt-confirm-btn-text,
     *   --mb-adapt-confirm-cancel-bg, --mb-adapt-confirm-cancel-text
     *
     * @default false
     */
    confirmOnClose?: boolean;
    /**
     * Callback invoked when session state changes.
     * Receives the status and optional fork identifier.
     *
     * @param status - Current session status (e.g., 'STATUS_RUNNING', 'STATUS_COMPLETED')
     * @param fork - Optional fork identifier (present for forked sessions)
     *
     * @example
     * ```typescript
     * onSession: (status, fork) => {
     *   console.log('Session status:', status);
     *   if (fork) console.log('Fork:', fork);
     * }
     * ```
     */
    onSession?: (status: StatusJson, fork?: string) => void;
    /**
     * Callback invoked when automation produces output.
     * Receives Output objects containing logs, data, or other results.
     *
     * @example
     * ```typescript
     * onOutput: (output) => {
     *   console.log('Output:', output);
     * }
     * ```
     */
    onOutput?: (output: Output) => void;
    /**
     * Callback invoked when a fork becomes visually active or inactive.
     * Active means the fork is taking up visual space (side-by-side non-collapsed, or dialog open).
     *
     * @param active - Whether a fork is visually active
     */
    onForkActive?: (active: boolean) => void;
    /**
     * Callback invoked when the automation encounters an error.
     * Receives a structured error with classification, message, and retriability.
     * Fires for both init-phase errors (e.g. invalid inheritToken) and streaming errors.
     *
     * @example
     * ```typescript
     * onError: (error) => {
     *   if (error.retriable) {
     *     console.log('Retriable error:', error.kind, error.message);
     *   } else {
     *     console.error('Fatal error:', error.kind, error.message);
     *   }
     * }
     * ```
     */
    onError?: (error: AdaptError) => void;
    /**
     * Custom CSS class names to override default styling.
     * All properties are optional. Unspecified classes use defaults.
     *
     * @example
     * ```typescript
     * // Using custom CSS classes
     * classNames: {
     *   root: 'my-adapt-container',
     *   iframe: 'my-iframe'
     * }
     * ```
     *
     * @example
     * ```typescript
     * // Using Tailwind classes
     * classNames: {
     *   root: 'w-full h-screen',
     *   iframe: 'rounded-lg shadow-xl'
     * }
     * ```
     */
    classNames?: {
        /** Root container class. Default: `'mb-adapt'` */
        root?: string;
        /** Iframe element class. Default: `'mb-adapt__iframe'` */
        iframe?: string;
        /** Status message overlay container. Default: `'mb-adapt__status-message'` */
        statusMessage?: string;
        /** Status card inside the overlay. Default: `'mb-adapt__status-card'` */
        statusCard?: string;
    };
    /**
     * Theme configuration for semantic theming.
     * Applies CSS custom properties to the root element based on semantic tokens.
     * Use `theme.vars` for direct per-variable overrides.
     *
     * @example
     * ```typescript
     * // Simple — match your brand
     * theme: { primary: '#FFF700' }
     *
     * // Full design system
     * theme: {
     *   mode: 'dark',
     *   primary: '#FFF700',
     *   background: '#121212',
     *   surface: '#1e1e1e',
     *   text: '#fff',
     *   border: 'rgba(255,255,255,0.12)',
     *   font: 'Inter, sans-serif',
     * }
     * ```
     */
    theme?: AdaptTheme;
    /**
     * Inline styles to apply to the root element.
     * Useful for quick positioning or sizing adjustments.
     *
     * @example
     * ```typescript
     * styles: {
     *   width: '100%',
     *   height: '600px',
     *   maxWidth: '1200px',
     *   margin: '0 auto'
     * }
     * ```
     */
    styles?: Partial<CSSStyleDeclaration>;
    /**
     * Enable session persistence across page refreshes.
     *
     * When enabled, the session token and URL state are stored in browser storage.
     * On page load, the client reconnects to the existing session instead of creating a new one.
     *
     * - `true` — use sessionStorage with 3600s TTL
     * - `PersistOptions` — customize storage type and TTL
     *
     * @default undefined (disabled)
     */
    persist?: boolean | PersistOptions;
    /**
     * Enable debug logging to the browser console.
     * When true, logs all session, persistence, URL, fork, and layout operations
     * with the `[Adapt]` prefix. Also activates debug logging in the core client.
     *
     * @default false
     */
    debug?: boolean;
    /**
     * Custom text overrides for status messages shown to the user.
     * Each property is optional — unspecified messages use built-in defaults.
     */
    text?: StatusText;
}
/**
 * Custom text overrides for status messages and error states.
 */
export interface StatusText {
    /** Shown when the session is stopped. Default: `"This session has been stopped"` */
    stopped?: string;
    /** Shown when the session token has expired. Default: `"Your session has expired."` */
    sessionExpired?: string;
    /** Shown on ResourceExhausted. Default: `"This automation is currently at capacity. Please try again later."` */
    resourceExhausted?: string;
    /** Shown on NotFound when automation doesn't exist. Default: `"This automation could not be found."` */
    notFound?: string;
    /** Shown on NotFound when session doesn't exist (timed out). Default: `"This session has timed out or been stopped."` */
    sessionNotFound?: string;
    /** Shown on PermissionDenied or Unauthenticated. Default: `"You don't have permission to run this automation."` */
    permissionDenied?: string;
    /** Shown on any other non-retriable error. Default: `"Something went wrong. Please try again later."` */
    error?: string;
    /** Label for the restart/try-again button on status cards. Default: `"Try again"` */
    restartButton?: string;
}
export type AdaptErrorKind = 'auth' | 'expired' | 'not_found' | 'session_not_found' | 'capacity' | 'error';
export interface AdaptError {
    kind: AdaptErrorKind;
    message: string;
    retriable: boolean;
    cause?: unknown;
}
