import type { CaptureRunEvents } from './Events';

export declare const backwardCompatibility: (parameter: SdkParameters) => void;

declare type CaptureModule = HostedModule | ExternalModule;

declare enum CaptureModuleType {
    HOSTED = "hosted",
    EXTERNAL = "external"
}

declare type ChallengePayload = {
    type: 'recite';
    query: number[];
} | {
    type: 'movement';
    query: string;
};

export declare type ClassicSdkParameters = {
    steps: LegacyStepDefinition[];
} & TokenParameters;

declare type Common = {
    sdk_metadata: string;
    sdk_source: string;
    sdk_version: string;
};

declare type CommonSdkParameters = {
    containerEl?: HTMLElement;
    containerId?: string;
    onError?: ErrorCallback_2;
    onComplete?: (data: CompleteData) => void;
    enterpriseFeatures?: EnterpriseFeatureParameter;
    theme?: Theme;
    customUI?: ThemeConfig;
    language?: string | LegacyLanguageParameter;
    translations?: Translations;
};

declare type CompleteData = Record<string, unknown>;

declare type CrossDeviceMethod = 'copy_link' | 'qr_code' | 'sms';

declare type CrossDevicePolicy = 'enable' | 'force' | 'disable';

declare type CrossDeviceSdkParameters = CommonSdkParameters & {
    roomId?: string;
};

declare type CustomCallbackFormatterType = 'raw' | 'formData';

declare type DocumentImageResponse = {
    applicant_id: string;
    type: DocumentType_2;
    side: DocumentSides;
    issuing_country: string;
    sdk_warnings: ImageQualityWarnings & {
        image_quality: {
            quality: string;
            breakdown: {
                document: {
                    has_document: boolean;
                    detection_score: number;
                } & Score;
                has_document: boolean;
                cutoff: {
                    has_cutoff: boolean;
                    score: number;
                } & Score;
                blur: {
                    has_blur: boolean;
                    score: number;
                    blur_model: string;
                } & Score;
                glare: {
                    score: number;
                    bbox: [number, number, number, number];
                    has_glare: boolean;
                    threshold: number;
                    glare_model: string;
                };
                barcode: {
                    result: string;
                    properties: Record<string, string>;
                };
            };
            image_quality_uuid: string;
        };
    };
    classification: {
        issuing_country: null;
        document_version: null;
        side?: DocumentSides;
        document_type?: DocumentType_2;
    };
    document_features: {
        has_nfc: boolean;
    };
} & UploadFileResponse;

declare type DocumentSides = 'front' | 'back';

declare type DocumentType_2 = 'driving_licence' | 'national_identity_card' | 'residence_permit' | 'passport';

declare type EnterpriseCallbackResponse<T> = {
    continueWithOnfidoSubmission?: boolean;
    onfidoSuccessResponse?: T;
};

declare type EnterpriseFeatureCallback = {
    useCustomizedApiRequests?: boolean;
    formatter?: CustomCallbackFormatterType;
    onSubmitDocument?: (data: FormData | SubmitDocument) => Promise<EnterpriseCallbackResponse<DocumentImageResponse>>;
    onSubmitSelfie?: (data: FormData | SubmitSelfie) => Promise<EnterpriseCallbackResponse<UploadFileResponse>>;
    onSubmitVideo?: (data: FormData | SubmitVideo) => Promise<EnterpriseCallbackResponse<FaceVideoResponse>>;
};

declare type EnterpriseFeatureParameter = EnterpriseFeatures & EnterpriseFeatureCallback;

declare type EnterpriseFeatures = {
    hideOnfidoLogo?: boolean;
    cobrand?: {
        text?: string;
    };
    logoCobrand?: {
        lightLogoSrc?: string;
        darkLogoSrc?: string;
    };
};

declare type ErrorCallback_2 = (error: {
    type: SdkErrorTypes;
    message: string;
    exception?: Error | unknown;
}) => void;

declare type Event_2<T extends string> = {
    type: T;
};

declare type ExternalModule = {
    url: string;
} & ModuleType<CaptureModuleType.EXTERNAL>;

declare type FaceVideoResponse = {
    challenge: ChallengePayload[];
    languages: VideoChallengeLanguage[];
} & UploadFileResponse;

export declare type Handle = {
    addEventListener: <EventName extends keyof CaptureRunEvents>(eventName: EventName, listener: Listener<CaptureRunEvents[EventName]>) => void;
    removeEventListener: <EventName extends keyof CaptureRunEvents>(eventName: EventName, listener: Listener<CaptureRunEvents[EventName]>) => void;
    tearDown: () => Promise<void>;
    version?: string;
};

declare type HostedModule = {
    version?: string;
    module: string;
} & ModuleType<CaptureModuleType.HOSTED>;

declare type ImageQualityValidationTypes = 'detect_barcode' | 'detect_document' | 'detect_cutoff' | 'detect_glare' | 'detect_blur';

declare type ImageQualityWarnings = Partial<Record<ImageQualityValidationTypes, {
    valid: boolean;
}>>;

declare type LegacyLanguageParameter = {
    locale?: string;
    phrases?: Record<string, string>;
    mobilePhrases?: Record<string, string>;
    direction?: LocaleDirection;
};

declare type LegacyStepDefinition = LegacyStepType | StepDefinition;

declare type LegacyStepType = 'welcome' | 'complete' | 'face' | 'consent' | 'document' | 'poa';

declare type Listener<E extends Event_2<any>> = (e: E) => void;

declare type LocaleDirection = 'ltr' | 'rtl';

declare type ModuleType<T extends CaptureModuleType> = {
    type: T;
};

export declare const Onfido: OnfidoApi;

export declare type OnfidoApi = {
    init: (parameter: SdkParameters) => Handle;
};

declare type Score = {
    min: number;
    max: number;
    threshold: number;
};

declare type SdkErrorTypes = 'invalid_token' | 'expired_token' | 'expired_trial' | 'geoblocked_request' | 'permissions_unavailable' | 'exception' | 'unsupported' | 'unsupported_feature' | 'invalid_sdk_parameter' | 'restart' | 'desktop' | 'unsupported_sdk_version' | 'no_camera' | 'user_consent_denied' | 'uncaught_fetch_error' | 'api_error' | 'cross_device_verification_invalid' | 'cross_device_verification_abort' | 'workflow_abandoned' | 'workflow_error' | 'workflow_input_error';

export declare type SdkParameters = StudioSdkParameters | ClassicSdkParameters | CrossDeviceSdkParameters;

declare type StepDefinition = {
    type: LegacyStepType | string;
    options?: Record<string, unknown>;
    module?: CaptureModule;
    /**
     * the key used to serialize the output for onComplete
     */
    key?: string;
};

export declare type StudioSdkParameters = {
    workflowRunId: string;
    disableWelcomeScreen?: boolean;
    onBiometricTokenGenerated?: (customerUserHash: string, biometricToken: string) => void;
    onBiometricTokenRequested?: (customerUserHash: string) => Promise<string>;
} & TokenParameters;

declare type SubmitDocument = {
    file: Blob;
    side: DocumentSides;
    type: string;
    sdk_validations: string;
} & Common;

declare type SubmitSelfie = {
    file: Blob;
    snapshot: {
        blob: Blob;
        filename: string;
    };
};

declare type SubmitVideo = {
    file: Blob;
    challenge: string;
    challenge_id: string;
    challenge_switch_at: number | undefined;
    languages: string;
};

declare type Theme = {
    name: 'light' | 'dark';
    config?: ThemeConfig;
};

declare type ThemeConfig = Record<string, any>;

declare type TokenParameters = {
    token: string;
    language?: string | LegacyLanguageParameter;
    translations?: Translations;
    theme?: Theme;
    /***
     * You can change the default country for the SMS number input by passing the
     * smsNumberCountryCode option when the SDK is initialized. The value should
     * be a string containing a 2-character ISO Country code. If empty, the SMS
     * number country code will default to GB.
     */
    smsNumberCountryCode?: string;
    userDetails?: UserDetails;
    _crossDeviceLinkMethods?: CrossDeviceMethod[];
    crossDeviceClientIntroProductLogoSrc?: string;
    crossDevicePolicy?: CrossDevicePolicy;
    disableAnalytics?: boolean;
    disableAnalyticsCookies?: boolean;
} & CommonSdkParameters;

declare type TranslationItem<T> = T | (() => Promise<T>);

declare type Translations<T = unknown> = Record<string, TranslationItem<T>>;

declare type UploadFileResponse = {
    id: string;
    created_at: string;
    file_name: string;
    file_type: string;
    file_size: number;
    href: string;
    download_href: string;
};

declare type UserDetails = {
    smsNumber?: string;
};

declare type VideoChallengeLanguage = {
    source: string;
    language_code: string;
};

export { }
