/**
 * WDS Biometric 2FA — Verifica da smartphone (pagina aperta scansionando
 * il QR mostrato sul PC). Stessa logica crittografica del flusso locale,
 * ma al termine si limita a segnalare "confermato": non imposta alcun
 * cookie qui, perché questo browser (il telefono) non è quello che deve
 * restare loggato — è il PC ad attendere la conferma tramite polling.
 */
( function () {
	'use strict';

	if ( typeof spidyBiometricLoginRemote === 'undefined' ) {
		return;
	}

	var button = document.getElementById( 'spidy-wp-login-remote-button' );
	var status = document.getElementById( 'spidy-wp-login-remote-status' );

	if ( ! button ) {
		return;
	}

	function base64urlToBuffer( base64url ) {
		var padding = '='.repeat( ( 4 - ( base64url.length % 4 ) ) % 4 );
		var base64  = ( base64url + padding ).replace( /-/g, '+' ).replace( /_/g, '/' );
		var raw     = atob( base64 );
		var buffer  = new ArrayBuffer( raw.length );
		var array   = new Uint8Array( buffer );
		for ( var i = 0; i < raw.length; i++ ) {
			array[ i ] = raw.charCodeAt( i );
		}
		return buffer;
	}

	function bufferToBase64url( buffer ) {
		var bytes  = new Uint8Array( buffer );
		var binary = '';
		for ( var i = 0; i < bytes.byteLength; i++ ) {
			binary += String.fromCharCode( bytes[ i ] );
		}
		return btoa( binary ).replace( /\+/g, '-' ).replace( /\//g, '_' ).replace( /=+$/, '' );
	}

	function setStatus( message, isError ) {
		status.textContent = message;
		status.style.color = isError ? '#b32d2e' : '#1a7f37';
	}

	button.addEventListener( 'click', function () {
		if ( ! window.PublicKeyCredential ) {
			setStatus( spidyBiometricLoginRemote.i18n.notSupported, true );
			return;
		}

		var opts = spidyBiometricLoginRemote.options;

		var publicKey = {
			challenge: base64urlToBuffer( opts.challenge ),
			rpId: opts.rpId,
			allowCredentials: opts.allowCredentials.map( function ( cred ) {
				return {
					id: base64urlToBuffer( cred.id ),
					type: cred.type,
					transports: cred.transports,
				};
			} ),
			userVerification: opts.userVerification,
			timeout: opts.timeout,
		};

		button.disabled = true;
		setStatus( spidyBiometricLoginRemote.i18n.verifying, false );

		navigator.credentials
			.get( { publicKey: publicKey } )
			.then( function ( assertion ) {
				var formData = new FormData();
				formData.append( 'action', 'spidy_wp_verify_assertion_remote' );
				formData.append( 'token', spidyBiometricLoginRemote.token );
				formData.append( 'credential_id', bufferToBase64url( assertion.rawId ) );
				formData.append( 'authenticator_data', bufferToBase64url( assertion.response.authenticatorData ) );
				formData.append( 'client_data_json', bufferToBase64url( assertion.response.clientDataJSON ) );
				formData.append( 'signature', bufferToBase64url( assertion.response.signature ) );
				if ( assertion.response.userHandle ) {
					formData.append( 'user_handle', bufferToBase64url( assertion.response.userHandle ) );
				}

				return fetch( spidyBiometricLoginRemote.ajaxUrl, { method: 'POST', body: formData, credentials: 'same-origin' } )
					.then( function ( res ) { return res.json(); } )
					.then( function ( data ) {
						if ( data.success ) {
							button.style.display = 'none';
							setStatus( spidyBiometricLoginRemote.i18n.done, false );
						} else {
							button.disabled = false;
							setStatus( data.data && data.data.message ? data.data.message : spidyBiometricLoginRemote.i18n.genericError, true );
						}
					} );
			} )
			.catch( function ( err ) {
				button.disabled = false;
				if ( err && err.name === 'NotAllowedError' ) {
					setStatus( spidyBiometricLoginRemote.i18n.cancelled, true );
				} else {
					setStatus( spidyBiometricLoginRemote.i18n.genericError, true );
				}
			} );
	} );
} )();
