'use client'
import { __awaiter } from '../../../../../_virtual/_tslib.js';
import { useCallback } from 'react';
import { authenticateTotpMfaDevice, getMfaDevices, setDefaultMfaDevice, deleteMfaDevice, registerTotpMfaDevice, authenticateMfaRecoveryCode, createNewMfaRecoveryCodes, getMfaRecoveryCodes, isPendingRecoveryCodesAcknowledgment, acknowledgeRecoveryCodes } from '@dynamic-labs-sdk/client';
import { MFADeviceType } from '@dynamic-labs/sdk-api-core';
import { verifyTotpMfaDevice } from '../../../client/extension/deprecated/mfa/verifyTotpMfaDevice/verifyTotpMfaDevice.js';
import '../../../client/client.js';
import '@dynamic-labs-sdk/client/core';
import '../../../config/ApiEndpoint.js';
import '@dynamic-labs/iconic';
import '@dynamic-labs/wallet-connector-core';
import 'react/jsx-runtime';
import '../../../context/ViewContext/ViewContext.js';
import '../../../shared/logger.js';
import '@dynamic-labs/wallet-book';
import '@dynamic-labs/utils';
import '../../constants/colors.js';
import '../../constants/values.js';
import '../../../shared/consts/index.js';
import '@dynamic-labs/multi-wallet';
import 'react-international-phone';
import '../../../store/state/nonce/nonce.js';
import '@dynamic-labs/locale';
import { refreshUserJwt } from '../../../data/api/user/user.js';
import { getEnvironmentId } from '../../../store/state/dynamicContextProps/dynamicContextProps.js';
import '../../../store/state/primaryWalletId/primaryWalletId.js';
import '../../../store/state/connectedWalletsInfo/connectedWalletsInfo.js';
import { dynamicEvents } from '../../../events/dynamicEvents.js';
import { useUserAuth } from '../useUserAuth/useUserAuth.js';

const useMfa = () => {
    const { completeAuth } = useUserAuth({});
    const handleMfaAuth = useCallback((_a) => __awaiter(void 0, [_a], void 0, function* ({ code, type, deviceId, createMfaToken, resultHandler, }) {
        let result;
        yield completeAuth({
            updateJwtFunction: () => __awaiter(void 0, void 0, void 0, function* () {
                if (type !== MFADeviceType.Totp) {
                    throw new Error('Only Totp is supported');
                }
                const response = yield authenticateTotpMfaDevice({
                    code,
                    createMfaTokenOptions: createMfaToken,
                    deviceId,
                });
                result = resultHandler(response);
                return {
                    isEmailVerificationRequired: false,
                    isSmsVerificationRequired: false,
                    missingFields: [],
                    updateUserProfileResponse: response,
                };
            }),
        });
        return result;
    }), [completeAuth]);
    const getUserDevices = useCallback(() => __awaiter(void 0, void 0, void 0, function* () {
        const devices = yield getMfaDevices();
        return devices;
    }), []);
    const updateUserDevice = useCallback((deviceId) => __awaiter(void 0, void 0, void 0, function* () {
        const devices = yield getMfaDevices();
        const device = devices.find((d) => d.id === deviceId);
        if (!device) {
            throw new Error('Device not found');
        }
        yield setDefaultMfaDevice({ deviceId });
    }), []);
    const deleteUserDevice = useCallback((deviceId, mfaAuthToken) => __awaiter(void 0, void 0, void 0, function* () {
        const devices = yield getMfaDevices();
        const device = devices.find((d) => d.id === deviceId);
        if (!device) {
            throw new Error('Device not found');
        }
        yield deleteMfaDevice({
            deviceId,
            mfaAuthToken,
        });
        // Refresh the user JWT to get the updated MFA acknowledgement
        // since if it is completed we won't show the QR code again
        yield refreshUserJwt({ environmentId: getEnvironmentId() });
    }), []);
    const addDevice = useCallback((...args_1) => __awaiter(void 0, [...args_1], void 0, function* (type = MFADeviceType.Totp) {
        if (type === MFADeviceType.Totp) {
            return registerTotpMfaDevice();
        }
        throw new Error('Unsupported MFA device type');
    }), []);
    const authDevice = useCallback((code_1, ...args_2) => __awaiter(void 0, [code_1, ...args_2], void 0, function* (code, type = MFADeviceType.Totp, deviceId) {
        let isValid = false;
        yield handleMfaAuth({
            code,
            deviceId,
            resultHandler: () => {
                isValid = true;
                return true;
            },
            type,
        });
        return isValid;
    }), [handleMfaAuth]);
    const authenticateDevice = useCallback((_b) => __awaiter(void 0, [_b], void 0, function* ({ code, type = MFADeviceType.Totp, deviceId, createMfaToken, }) {
        return handleMfaAuth({
            code,
            createMfaToken,
            deviceId,
            resultHandler: (response) => response.mfaToken,
            type,
        });
    }), [handleMfaAuth]);
    const authRecoveryCode = useCallback((code) => __awaiter(void 0, void 0, void 0, function* () {
        let isValid = false;
        yield completeAuth({
            onValidUpdatedJwt: () => __awaiter(void 0, void 0, void 0, function* () {
                isValid = true;
            }),
            updateJwtFunction: () => __awaiter(void 0, void 0, void 0, function* () {
                const response = yield authenticateMfaRecoveryCode({
                    code,
                    createMfaTokenOptions: { singleUse: true },
                });
                if (!response) {
                    throw new Error('Failed to authenticate recovery code');
                }
                dynamicEvents.emit('mfaCompletionSuccess', {
                    mfaToken: response.mfaToken,
                });
                return {
                    isEmailVerificationRequired: false,
                    isSmsVerificationRequired: false,
                    missingFields: [],
                    // in the mfa flow, we only care about the user in the response
                    updateUserProfileResponse: response,
                };
            }),
        });
        return isValid;
    }), [completeAuth]);
    const authenticateRecoveryCode = useCallback((_c) => __awaiter(void 0, [_c], void 0, function* ({ code, createMfaToken, }) {
        let mfaToken = undefined;
        yield completeAuth({
            updateJwtFunction: () => __awaiter(void 0, void 0, void 0, function* () {
                const response = yield authenticateMfaRecoveryCode({
                    code,
                    createMfaTokenOptions: createMfaToken,
                });
                if (!response) {
                    throw new Error('Failed to authenticate recovery code');
                }
                // eslint-disable-next-line prefer-destructuring
                mfaToken = response.mfaToken;
                dynamicEvents.emit('mfaCompletionSuccess', {
                    mfaToken: response.mfaToken,
                });
                return {
                    isEmailVerificationRequired: false,
                    isSmsVerificationRequired: false,
                    missingFields: [],
                    // in the mfa flow, we only care about the user in the response
                    updateUserProfileResponse: response,
                };
            }),
        });
        return mfaToken;
    }), [completeAuth]);
    const verifyDevice = useCallback((code_2, ...args_3) => __awaiter(void 0, [code_2, ...args_3], void 0, function* (code, type = MFADeviceType.Totp) {
        if (type === MFADeviceType.Totp) {
            const device = yield verifyTotpMfaDevice({
                code,
            });
            if (!device) {
                throw new Error('Failed to verify device');
            }
            return device;
        }
        throw new Error('Unsupported MFA device type');
    }), []);
    const getRecoveryCodes = useCallback((...args_4) => __awaiter(void 0, [...args_4], void 0, function* (
    /**
     * @deprecated use getNewRecoveryCodes instead
     */
    generateNewCodes = false) {
        if (generateNewCodes) {
            const { recoveryCodes } = yield createNewMfaRecoveryCodes();
            return recoveryCodes;
        }
        else {
            const { recoveryCodes } = yield getMfaRecoveryCodes();
            return recoveryCodes;
        }
    }), []);
    const getNewRecoveryCodes = useCallback(() => __awaiter(void 0, void 0, void 0, function* () {
        const { recoveryCodes } = yield createNewMfaRecoveryCodes();
        return recoveryCodes;
    }), []);
    const isPendingRecoveryCodesAcknowledgment$1 = useCallback(() => __awaiter(void 0, void 0, void 0, function* () { return isPendingRecoveryCodesAcknowledgment(); }), []);
    const completeAcknowledgement = useCallback(() => __awaiter(void 0, void 0, void 0, function* () {
        yield acknowledgeRecoveryCodes();
    }), []);
    return {
        addDevice,
        authDevice,
        authRecoveryCode,
        authenticateDevice,
        authenticateRecoveryCode,
        completeAcknowledgement,
        deleteUserDevice,
        getNewRecoveryCodes,
        getRecoveryCodes,
        getUserDevices,
        isPendingRecoveryCodesAcknowledgment: isPendingRecoveryCodesAcknowledgment$1,
        updateUserDevice,
        verifyDevice,
    };
};

export { useMfa };
