import { CreateSessionOptions } from '@incodetech/core/session';
import { CustomModuleCallback } from '@incodetech/core/workflow';
import { FC } from 'preact/compat';
import { FinishStatus } from '@incodetech/core/flow';
import { WasmConfig } from '@incodetech/core/wasm';

declare type ApiKeySessionBootstrap = {
    apiKey: string;
    clientId?: string;
};

declare type ClientIdSessionBootstrap = {
    apiKey?: string;
    clientId: string;
};

declare type IncodeModuleProps<TConfig, TResult = void, TManager = unknown> = {
    /**
     * Module configuration required to render the flow.
     * For Web Components, this is typically assigned via `element.config = ...`.
     */
    config?: TConfig;
    /**
     * Optional pre-built manager. When provided, the module does not create or manage the manager lifecycle.
     */
    manager?: TManager;
    /**
     * Callback invoked when the module completes successfully.
     * @param result - Optional result data from the module completion
     */
    onFinish?: (result?: TResult) => void;
    /**
     * Callback invoked when a fatal module error occurs.
     *
     * @param error - Human-readable error message.
     * @param errorCode - Optional numeric code (e.g. HTTP status). Populated by
     *   the workflow and flow modules on QR validation failures —
     *   `4026` (`expiredUUID`), `4081` (`invalidQRuuid`) or `4083` (`onboardingUrlAlreadyUsed`).
     * @param moduleErrorCode - Optional machine-readable error code (e.g. a
     *   `FaceErrorCode` such as `NONEXISTENT_CUSTOMER`). Lets an orchestrator
     *   branch on the specific terminal error without parsing the message string.
     */
    onError?: (error: string | undefined, errorCode?: number, moduleErrorCode?: string) => void;
};

export declare const IncodeWorkflow: FC<IncodeWorkflowProps>;

declare type IncodeWorkflowProps = IncodeModuleProps<WorkflowComponentConfig, FinishStatus>;

export declare function mapModuleConfig(options: MapModuleConfigOptions): Record<string, unknown>;

/**
 * Maps backend moduleConfiguration to the shape each UI component expects.
 * Most modules receive config as-is. Some need field renaming or extra fields.
 */
declare type MapModuleConfigOptions = {
    moduleKey: string;
    config: Record<string, unknown>;
    workflowId: string;
    authHint?: string;
    lang?: string;
    mergeSessionRecordings?: boolean;
    ageAssurance?: boolean;
};

declare type SelfLoadingSessionOptions = Pick<CreateSessionOptions, 'configurationId' | 'externalId' | 'externalCustomerId' | 'customFields' | 'uuid' | 'urlUuid' | 'loginHint'>;

declare type SelfLoadingWorkflowRuntimeConfig = WorkflowBaseConfig & SelfLoadingSessionOptions & (ApiKeySessionBootstrap | ClientIdSessionBootstrap) & {
    token?: never;
    /**
     * `interviewId` is resolved from the session response — passing one
     * explicitly is rejected at the type level. Use token mode if you need
     * to bind a pre-existing interview.
     */
    interviewId?: never;
};

declare type SpinnerConfig = {
    title?: string;
    subtitle?: string;
    size?: SpinnerSize;
};

declare type SpinnerSize = 'small' | 'medium' | 'large';

declare type TokenWorkflowRuntimeConfig = WorkflowBaseConfig & {
    token: string;
    /**
     * Interview ID from an existing session. Required for custom-module
     * processing. Only valid in token mode — in self-loading mode the SDK
     * resolves it from `POST /omni/start` and overriding it is rejected.
     */
    interviewId?: string;
    /**
     * QR anti-phishing token from the incoming URL. When provided, the SDK
     * burns it via `POST /omni/qr/validate` on mount and invokes
     * `onUrlUuidRefreshed` with the rotated value so the host can update the
     * address bar (e.g., `history.replaceState`). Validation failures abort
     * initialization and surface via the SDK's terminal error screen.
     */
    urlUuid?: string;
    apiKey?: never;
    clientId?: never;
    configurationId?: never;
    externalId?: never;
    externalCustomerId?: never;
    customFields?: never;
    uuid?: never;
};

declare type WorkflowBaseConfig = {
    lang?: string;
    disableDashboardTheme?: boolean;
    wasmConfig?: WasmConfig | false;
    spinnerConfig?: SpinnerConfig;
    customModuleCallback?: CustomModuleCallback;
    /** Whether the device is a desktop. Determines desktop-to-mobile redirect injection. Defaults to true. */
    isDesktop?: boolean;
    /** Authentication hint for AUTHENTICATION module. Required when workflow includes face authentication. */
    authHint?: string;
    onModuleLoading?: (moduleKey: string) => void;
    onModuleLoaded?: (moduleKey: string) => void;
    onUrlUuidRefreshed?: (urlUuid: string) => void;
};

export declare type WorkflowComponentConfig = TokenWorkflowRuntimeConfig | SelfLoadingWorkflowRuntimeConfig;

export { }

declare global {
    interface HTMLElementTagNameMap {
        'incode-workflow': HTMLElement & IncodeModuleProps<WorkflowComponentConfig,
  FinishStatus>;
    }
}
