/**
 * Copyright © 2025 Nevis Security AG. All rights reserved.
 */

import uuid from 'react-native-uuid';

import { FidoUafAttestationInformation } from './FidoUafAttestationInformation';
import { FidoUafAttestationInformationError } from '../error/attestationInformation/FidoUafAttestationInformationError';
import { FidoUafAttestationInformationErrorConverter } from '../error/attestationInformation/FidoUafAttestationInformationErrorConverter';
import NevisMobileAuthenticationSdkReact from '../MobileAuthenticationSdk';
import { OnSuccessMessage } from '../model/messages/in/OnSuccessMessage';
import { FidoUafAttestationInformationMessage } from '../model/messages/out/FidoUafAttestationInformationMessage';
import { Operation } from '../operations/Operation';

/**
 * The object that can be used to obtain the information regarding the support of
 * {@link https://docs.nevis.net/configurationguide/mobile-auth-concept-and-integration-guide/use-cases-and-best-practices/uaf-surrogate-full-basic-comparison | Full Basic Attestation}
 * in this device.
 *
 * > [!IMPORTANT]
 * > This operation is Android specific. On iOS the {@link onSuccess} will be invoked with `undefined`
 * > FIDO UAF attestation information.
 *
 * If full basic attestation is required by the backend during registration, and this device does not
 * support it, registration will fail. This information can be used to preemptively inform the user
 * that the device is not supported.
 *
 * Usage example:
 * ```ts
 *  async function getAttestationInformation(
 *      client: MobileAuthenticationClient,
 *  ): Promise<void> {
 *      await client.deviceCapabilities
 *          .androidDeviceCapabilities
 *          .fidoUafAttestationInformationGetter
 *          .onSuccess((FidoUafAttestationInformation? info) {
 *              // handle success
 *          })
 *          .onError((error) {
 *              // handle error
 *          })
 *          .execute();
 *  }
 * ```
 *
 * @group Performing Operations
 * @see {@link AndroidDeviceCapabilities.fidoUafAttestationInformationGetter}
 */
export abstract class FidoUafAttestationInformationGetter extends Operation {
	/**
	 * Disables Certificate Revocation List (CRL) checking for {@link FidoUafAttestationInformationGetter}.
	 * FIDO UAF attestation information will be retrieved without checking the revocation of the device's certification
	 * on the CRL published by Google {@link https://android.googleapis.com/attestation/status | here}.
	 *
	 * By default, the CRL check is enabled.
	 *
	 * @returns a {@link FidoUafAttestationInformationGetter} object.
	 */
	abstract disableCrlCheck(): FidoUafAttestationInformationGetter;

	/**
	 * Specifies the object that will be invoked if the FIDO UAF attestation information could be
	 * obtained. The specified object will receive an optional {@link FidoUafAttestationInformation}.
	 *
	 * > [!IMPORTANT]
	 * > Providing the `onSuccess` callback is required.
	 *
	 * @param onSuccess the callback which will be invoked if the FIDO UAF attestation information
	 * could be obtained.
	 * @returns a {@link FidoUafAttestationInformationGetter} object.
	 */
	abstract onSuccess(
		onSuccess: (fidoUafAttestationInformation?: FidoUafAttestationInformation) => void
	): FidoUafAttestationInformationGetter;

	/**
	 * Specifies the object that will be invoked if the FIDO UAF attestation information could not be
	 * obtained.
	 *
	 * > [!IMPORTANT]
	 * > Providing the `onError` callback is required.
	 *
	 * @param onError the callback which receives a {@link FidoUafAttestationInformationError}.
	 * @returns a {@link FidoUafAttestationInformationGetter} object.
	 */
	abstract onError(
		onError: (error: FidoUafAttestationInformationError) => void
	): FidoUafAttestationInformationGetter;
}

export class FidoUafAttestationInformationGetterImpl extends FidoUafAttestationInformationGetter {
	private _disableCrlCheck: boolean = false;
	private _onSuccess?: (fidoUafAttestationInformation?: FidoUafAttestationInformation) => void;
	private _onError?: (error: FidoUafAttestationInformationError) => void;

	disableCrlCheck(): FidoUafAttestationInformationGetter {
		this._disableCrlCheck = true;
		return this;
	}

	onSuccess(
		onSuccess: (fidoUafAttestationInformation?: FidoUafAttestationInformation) => void
	): FidoUafAttestationInformationGetter {
		this._onSuccess = onSuccess;
		return this;
	}

	onError(
		onError: (error: FidoUafAttestationInformationError) => void
	): FidoUafAttestationInformationGetter {
		this._onError = onError;
		return this;
	}

	async execute(): Promise<void> {
		const operationId = uuid.v4();

		const message = new FidoUafAttestationInformationMessage(
			operationId,
			this._disableCrlCheck,
			this._onSuccess !== undefined,
			this._onError !== undefined
		);

		return NevisMobileAuthenticationSdkReact.fidoUafAttestationInformation(message)
			.then((result: OnSuccessMessage) => {
				const successMessage = OnSuccessMessage.fromJson(result);
				this._onSuccess?.(successMessage.fidoUafAttestationInformation);
			})
			.catch((error: Error) => {
				const attestationError = new FidoUafAttestationInformationErrorConverter(
					error
				).convert();
				this._onError?.(attestationError);
			});
	}
}
