import { useState, useEffect, useCallback } from 'react'; //, useCallback, useSyncExternalStore, useMemo
// import { PopOver } from './PopOver';
import { WpInlineScript } from '../interfaces';
import Window from './Window';
import Loader from './Loader';
import queryString from 'query-string';
import { Transition } from '@headlessui/react';
import Documentation from './step/Documentation';

declare const webEngineAccount: WpInlineScript;
declare const webEngineCaptcha: WpInlineScript;

export const App = () => {
	const [ loaded, setLoaded ] = useState( false );
	const [ status, setStatus ] = useState( 'init' );
	const [ error, setError ] = useState( '' );
	const [ pin, setPin ] = useState( '' );
	const [ mailStep, setMailStep ] = useState( 0 ); // 0 = not sent, 1 = pending, 2 = sent, 3 == error
	const [ notice, setNotice ] = useState();
	const [ balance, setBalance ] = useState( 0 );
	const [ newUser, setNewUser ] = useState( false );
	const [ registrationEmail, setRegistrationEmail ] = useState( '' );
	const [ registrationName, setRegistrationName ] = useState( '' );
	const [ testMode, setTestMode ] = useState( false );
	const [ logged, setLogged ] = useState( false );
	const [ expires, setExpires ] = useState( -1 );
	const [ commAdministrative, setCommAdministrative ] = useState( false );
	const [ commNews, setCommNews ] = useState( false );
	const [ commDeveloper, setCommDeveloper ] = useState( false );

	// Used on register and after. Only want to update the state when registering.
	function handleCommAdministrativeChange( opt: boolean, update: boolean ) {
		if ( true === update ) {
			updateComm( 'comm_administrative', opt, setCommAdministrative );
		} else {
			setCommAdministrative( opt );
		}
	}
	function handleCommNewsChange( opt: boolean, update: boolean ) {
		if ( true === update ) {
			updateComm( 'comm_news', opt, setCommNews );
		} else {
			setCommNews( opt );
		}
	}
	function handleCommDeveloperChange( opt: boolean, update: boolean ) {
		if ( true === update ) {
			updateComm( 'comm_developer', opt, setCommDeveloper );
		} else {
			setCommDeveloper( opt );
		}
	}
	function updateComm( option: string, value: any, callback: Function ) {
		if ( ! loaded ) {
			return;
		}
		const data = {
			action: 'we360cloud_account',
			token: webEngineAccount.token,
			route: 'updatecomm',
			option,
			value,
		};
		fetch( webEngineCaptcha.url, {
			method: 'POST',
			headers: {
				'content-type': 'application/x-www-form-urlencoded',
			},
			body: queryString.stringify( data ),
		} )
			.then( ( response ) => response.json() )
			.then( ( json ) => {
				callback( json.payload.value === true );
			} );
	}

	const onStep = ( requestedStep: string ) => {
		switch ( requestedStep ) {
			case 'reload':
				init();
				break;
			case 'manage':
				// load the data!
				setStatus( 'manage' );
				break;
			case 'documentation':
				// load the data!
				setStatus( 'documentation' );
				break;
			case 'authenticated':
				setStatus( 'authenticated' );
				break;
			case 'newly-authenticated':
				init();
				setStatus( 'authenticated' );
				break;
			case 'force-disconnect':
				// user really wants to disconnect from  Web-Engine cloud completely
				setStatus( 'force-disconnect' );
				break;
			case 'force-disconnect-confirmed':
				// user really wants to disconnect from  Web-Engine cloud completely
				const udata2 = {
					action: 'we360cloud_account',
					token: webEngineAccount.token,
					route: 'goodbye',
				};
				fetch( webEngineAccount.url, {
					method: 'POST',
					headers: {
						'content-type': 'application/x-www-form-urlencoded',
					},
					body: queryString.stringify( udata2 ),
				} )
					.then( ( response ) => response.json() )
					.then( ( data ) => {
						if ( data.code === 200 ) {
							setLoaded( true );
							setStatus( 'register' );
						} else {
							setLoaded( true );
							setStatus( 'error' );
						}
					} );
				break;
			// this is just sentry
			case 'unregister':
				setStatus( 'unregister' );
				break;
			// this is just sentry
			case 'unregister-confirmed':
				setLoaded( false );
				const udata = {
					action: 'we360cloud_sentry',
					token: webEngineCaptcha.token,
					we360cloud_sentry_route: 'goodbye',
				};
				fetch( webEngineCaptcha.url, {
					method: 'POST',
					headers: {
						'content-type': 'application/x-www-form-urlencoded',
					},
					body: queryString.stringify( udata ),
				} )
					.then( ( response ) => response.json() )
					.then( ( data ) => {
						if ( data.code === 200 ) {
							setLoaded( true );
							setStatus( 'activate' );
						} else {
							setLoaded( true );
							setStatus( 'error' );
						}
					} );
				break;
			case 'exit-testmode':
				setLoaded( false );
				const capdata = {
					action: 'we360cloud_sentry',
					token: webEngineCaptcha.token,
					we360cloud_sentry_route: 'goodbye',
				};
				fetch( webEngineAccount.url, {
					method: 'POST',
					headers: {
						'content-type': 'application/x-www-form-urlencoded',
					},
					body: queryString.stringify( capdata ),
				} )
					.then( ( response ) => response.json() )
					.then( ( capjson ) => {
						setLoaded( true );
						if ( capjson.code === 200 ) {
							setTestMode( false );
							setStatus( 'register' );
						} else {
							setStatus( 'error' );
						}
					} );
				break;
			case 'pin':
				setStatus( 'registering' );
				const pdata = {
					action: 'we360cloud_account',
					token: webEngineAccount.token,
					route: 'hello',
					name: registrationName,
					email: registrationEmail,
				};
				fetch( webEngineAccount.url, {
					method: 'POST',
					headers: {
						'content-type': 'application/x-www-form-urlencoded',
					},
					body: queryString.stringify( pdata ),
				} )
					.then( ( response ) => response.json() )
					.then( ( json ) => {
						// ::TODO:: look at the json - make sure the response was a send
						if ( true === json.success ) {
							setStatus( 'pin sent' );
						} else {
							//::TODO:: inform that there was an issue with the issue of
							// the pin as otherwise we are stuck here
							setStatus( 'register' );
						}
					} );
				break;
			case 'bad pin':
				setStatus( 'bad pin' );
				break;
			case 'pin check':
				setStatus( 'pin check' );
				const pcdata = {
					action: 'we360cloud_account',
					token: webEngineAccount.token,
					route: 'hello',
					name: registrationName,
					email: registrationEmail,
					commAdministrative,
					commNews,
					commDeveloper,
					pin,
				};
				fetch( webEngineAccount.url, {
					method: 'POST',
					headers: {
						'content-type': 'application/x-www-form-urlencoded',
						//'token': webEngineAccount.token
					},
					// headers: { 'Content-Type': 'application/json' },
					body: queryString.stringify( pcdata ),
				} )
					.then( ( response ) => response.json() )
					.then( ( data ) => {
						if (
							false === data.success ||
							Number( data.code ) !== 200
						) {
							setStatus( 'error pin' );
						} else if ( 'authenticated' === data.status ) {
							if (
								false === data.success ||
								Number( data.code ) !== 200
							) {
								setStatus( 'error pin' );
							} else if ( 'authenticated' === data.status ) {
								onStep( 'sentry-setup' );
								setBalance( data.balance );
								setNewUser( data.newUser );
								setLogged( data.logged );
							} else {
								setStatus( 'bad pin' );
							}
						}
					} );
				break;

			case 'sentry-setup':
				setLoaded( false );
				const setupdata = {
					action: 'we360cloud_sentry',
					token: webEngineCaptcha.token,
					we360cloud_sentry_route: 'sentrysetup',
				};
				fetch( webEngineCaptcha.url, {
					method: 'POST',
					headers: {
						'content-type': 'application/x-www-form-urlencoded',
					},
					body: queryString.stringify( setupdata ),
				} )
					.then( ( response ) => response.json() )
					.then( ( json ) => {
						// email sent, set to 2 (success)
						if ( true === json.success ) {
							setLoaded( true );
							setStatus( 'welcome' );
							setMailStep( 0 );
						} else {
							// setLoaded( true );
							setError( 'Error with sentry setup' );
							window.setTimeout( () => {
								location.reload();
							}, 10000 );
						}
					} );
				break;

			case 'password-setup':
				setMailStep( 1 );
				const psdata = {
					action: 'we360cloud_account',
					token: webEngineAccount.token,
					route: 'resetemail',
					name: registrationName,
					email: registrationEmail,
				};
				fetch( webEngineAccount.url, {
					method: 'POST',
					headers: {
						'content-type': 'application/x-www-form-urlencoded',
					},
					body: queryString.stringify( psdata ),
				} )
					.then( ( response ) => response.json() )
					.then( ( json ) => {
						// email sent, set to 2 (success)
						if ( true === json.success ) {
							setMailStep( 2 );
						} else {
							// error, set to 3 (error message)
							setMailStep( 3 );
						}
					} );
				break;
			default:
				setStatus( 'register' );
		}
	};

	const init = useCallback( () => {
		setLoaded( false );
		const idata = {
			action: 'we360cloud_account',
			token: webEngineAccount.token,
			route: 'hello',
		};
		fetch( webEngineAccount.url, {
			method: 'POST',
			headers: {
				'content-type': 'application/x-www-form-urlencoded',
				//'token': webEngineAccount.token
			},
			// headers: { 'Content-Type': 'application/json' },
			body: queryString.stringify( idata ),
		} )
			.then( ( response ) => response.json() )
			.then( ( data ) => {
				if (
					false === data ||
					( data.code && Number( data.code ) !== 200 )
				) {
					setLoaded( true );
					setStatus( 'error' );
				} else {
					// check captcha option
					if ( data.email ) {
						setRegistrationEmail( data.email );
					}
					if ( data.name ) {
						setRegistrationName( data.name );
					}
					setLogged( data.logged );
					setExpires( data.expires );
					if (
						! data.products ||
						! data.products.includes( 'sentry' )
					) {
						if ( data.status === 'register' ) {
							setLoaded( true );
							setStatus( data.status );
						} else if ( data.status === 'reset' ) {
							// malformed token. reset
							setLoaded( true );
							setStatus( 'register' );
						} else {
							setLoaded( true );
							setStatus( 'activate' );
						}
						return;
					}
					const rqdata = {
						action: 'we360cloud_sentry',
						token: webEngineCaptcha.token,
						we360cloud_sentry_route: 'testmode',
					};
					fetch( webEngineAccount.url, {
						method: 'POST',
						headers: {
							'content-type': 'application/x-www-form-urlencoded',
						},
						body: queryString.stringify( rqdata ),
					} )
						.then( ( response ) => response.json() )
						.then( ( json ) => {
							setLoaded( true );
							if ( json.code === 200 ) {
								setTestMode( json.testmode );
								if ( false === data.success ) {
									setStatus( 'error' );
								} else if ( 'authenticated' !== data.status ) {
									setStatus( data.status );
								}
								if ( data.notice ) {
									setNotice( data.notice );
								} else {
									setNotice( undefined );
								}
								setCommAdministrative(
									data.communications.commAdministrative === 1
								);
								setCommNews(
									data.communications.commNews === 1
								);
								setCommDeveloper(
									data.communications.commDeveloper === 1
								);
								setBalance( data.balance );
								if ( true === json.testmode ) {
									setStatus( 'authenticated' );
								} else {
									setStatus( 'manage' );
								}
							} else {
								setStatus( 'error' );
							}
						} );
				}
			} );
	}, [] );

	useEffect( () => {
		// Anything in here is fired on component mount.
		init();
		return () => {
			// Anything in here is fired on component unmount.
		};
	}, [ init ] );
	return (
		<div className="pointer-events-auto relative top-0 left-0 w-full pr-[20px] pt-[20px]">
			<div className="inset-0 z-10 w-full">
				<div className="flex min-h-full items-end sm:p-0">
					<div className="relative flex">
						<Transition
							as="div"
							show={
								true === loaded &&
								'documentation' !== status &&
								'manage' !== status
							}
							enter="transform transition duration-300 ease-out origin-top-left"
							enterFrom="opacity-0 -translate-x-full"
							enterTo="opacity-100 translate-x-0"
							leave="hidden transform duration-0 transition ease-in"
							leaveFrom="opacity-100 translate-x-0"
							leaveTo="opacity-0 translate-x-full"
						>
							<Window
								registrationStep={ status }
								registrationEmail={ registrationEmail }
								registrationName={ registrationName }
								commAdministrative={ commAdministrative }
								commNews={ commNews }
								commDeveloper={ commDeveloper }
								notice={ notice }
								pin={ pin }
								balance={ balance }
								newUser={ newUser }
								testMode={ testMode }
								mailStep={ mailStep }
								onPin={ ( val: string ) => {
									setPin( val );
								} }
								onStep={ ( step: string ) => {
									onStep( step );
								} }
								onRegistrationEmail={ ( email: string ) => {
									setRegistrationEmail( email );
								} }
								onRegistrationName={ ( name: string ) => {
									setRegistrationName( name );
								} }
								onCommAdministrative={ (
									opt: boolean,
									update: boolean = false
								) => {
									handleCommAdministrativeChange(
										opt,
										update
									);
								} }
								onCommNews={ (
									opt: boolean,
									update: boolean = false
								) => {
									handleCommNewsChange( opt, update );
								} }
								onCommDeveloper={ (
									opt: boolean,
									update: boolean = false
								) => {
									handleCommDeveloperChange( opt, update );
								} }
								logged={ logged }
								expires={ expires }
							/>
						</Transition>
						<Transition
							as="div"
							show={
								true === loaded && 'documentation' === status
							}
							enter="transform transition duration-300 ease-out origin-top-left"
							enterFrom="-translate-x-full"
							enterTo="translate-x-0"
							leave="hidden transform duration-0 transition ease-in"
							leaveFrom="opacity-100"
							leaveTo="opacity-0"
						>
							<Documentation
								registrationEmail={ registrationEmail }
								registrationName={ registrationName }
								testMode={ testMode }
								onStep={ ( step: string ) => {
									onStep( step );
								} }
								logged={ logged }
							/>
						</Transition>
						<Transition
							as="div"
							show={ true === loaded && 'manage' === status }
							enter="transform transition duration-300 ease-out origin-top-left"
							enterFrom="-translate-x-full"
							enterTo="translate-x-0"
							leave="hidden transform duration-0 transition ease-in"
							leaveFrom="opacity-100"
							leaveTo="opacity-0"
						>
							<Window
								registrationStep={ status }
								registrationEmail={ registrationEmail }
								registrationName={ registrationName }
								commAdministrative={ commAdministrative }
								commNews={ commNews }
								commDeveloper={ commDeveloper }
								notice={ notice }
								pin={ pin }
								balance={ balance }
								newUser={ newUser }
								testMode={ testMode }
								mailStep={ mailStep }
								onPin={ ( val: string ) => {
									setPin( val );
								} }
								onStep={ ( step: string ) => {
									onStep( step );
								} }
								onRegistrationEmail={ ( email: string ) => {
									setRegistrationEmail( email );
								} }
								onRegistrationName={ ( name: string ) => {
									setRegistrationName( name );
								} }
								onCommAdministrative={ (
									opt: boolean,
									update: boolean = false
								) => {
									handleCommAdministrativeChange(
										opt,
										update
									);
								} }
								onCommNews={ (
									opt: boolean,
									update: boolean = false
								) => {
									handleCommNewsChange( opt, update );
								} }
								onCommDeveloper={ (
									opt: boolean,
									update: boolean = false
								) => {
									handleCommDeveloperChange( opt, update );
								} }
								logged={ logged }
								expires={ expires }
							/>
						</Transition>

						{ true !== loaded && (
							<Loader visible={ ! loaded } error={ error } />
						) }
					</div>
				</div>
			</div>
		</div>
	);
};
export default App;
