/**
 * WordPress dependencies
 */
import { useDispatch, useSelect } from '@wordpress/data';
import { useEffect, useState } from '@wordpress/element';

/**
 * Internal dependencies
 */
import { store as NAB_CHECKER } from '../store';
import { removeCookie, setCookie } from '../../public/utils/cookies';

export const Status = (): JSX.Element => (
	<div>
		<CloudStatus />
		<PageStatus />
		<AlternativeSelector />
	</div>
);

// =====
// VIEWS
// =====

function CloudStatus() {
	const cloudStatus = useSelect(
		( select ) => select( NAB_CHECKER ).getCloudStatus(),
		[]
	);

	return (
		<div style={ { marginTop: '1em' } }>
			<div
				style={ {
					display: 'flex',
					alignItems: 'center',
					gap: '0.5em',
				} }
			>
				<span
					style={ {
						display: 'block',
						width: '1em',
						height: '1em',
						fontSize: '10px',
						borderRadius: '100%',
						backgroundColor:
							// eslint-disable-next-line no-nested-ternary
							'pending' === cloudStatus
								? '#aab'
								: 'reachable' === cloudStatus
								? '#62b862'
								: '#ff2e2e',
					} }
				/>
				<strong>Cloud</strong>
			</div>
			{ 'unreachable' === cloudStatus && (
				<div style={ { marginLeft: '1em' } }>
					<span style={ { fontSize: '0.8em' } }>
						Cloud is not reachable and, therefore, events can’t be
						properly tracked.
					</span>
				</div>
			) }
		</div>
	);
}

function PageStatus() {
	return (
		<div style={ { marginTop: '1em' } }>
			<div>
				<strong>Page Status</strong>
			</div>
			<div style={ { marginLeft: '1em' } }>
				<div style={ { fontSize: '0.8em' } }>
					<PageStatusContent />
				</div>
			</div>
		</div>
	);
}

function PageStatusContent(): JSX.Element | string {
	const { isAwaitingGdpr, status } = useSelect(
		( select ) => ( {
			isAwaitingGdpr: select( NAB_CHECKER ).isAwaitingGdpr(),
			status: select( NAB_CHECKER ).getStatus(),
		} ),
		[]
	);

	switch ( status.type ) {
		case 'missing-settings':
			return (
				<>
					Global object <code>nabSettings</code> is missing.
				</>
			);

		case 'bootstrap':
			switch ( status.detail ) {
				case 'missing-session':
					return 'Something went wrong. Visitor can’t be tested.';

				case 'awaiting-session':
					return 'Awaiting session…';

				case 'awaiting-variant':
					return 'Loading variant…';
			}

		// eslint-disable-next-line no-fallthrough
		case 'content-ready':
			if ( isAwaitingGdpr ) {
				return 'Awaiting GDPR consent…';
			}

			return status.isTestVariant
				? 'Variant content ready'
				: 'Untested content ready';
	}
}

function AlternativeSelector() {
	const {
		actualAlternative,
		cookieTesting,
		maxCombinations,
		newAlternative,
	} = useSelect(
		( select ) => ( {
			actualAlternative: select( NAB_CHECKER ).getAlternative(),
			cookieTesting: select( NAB_CHECKER ).getSettings().cookieTesting,
			maxCombinations:
				select( NAB_CHECKER ).getSettings().maxCombinations,
			newAlternative: select( NAB_CHECKER ).getNewAlternative(),
		} ),
		[]
	);
	const { setNewAlternative } = useDispatch( NAB_CHECKER );

	const [ locked, lock ] = useState( false );
	const isDirty = newAlternative !== actualAlternative;

	const onClick = () => {
		lock( true );
		setCookie( 'nabAlternative', newAlternative, { expires: 120 } );
		removeCookie( 'nabExperimentsWithPageViews' );
		removeCookie( 'nabUniqueViews' );

		if ( false === cookieTesting ) {
			const url = new URL( window.location.href );
			url.searchParams.set( 'nab', `${ newAlternative }` );
			window.location.href = url.toString();
		} else {
			window.location.reload();
		}
	};

	return (
		<div style={ { marginTop: '1em' } }>
			<div>
				<label htmlFor="nab-checker-alternative">
					<strong>nabAlternative</strong>
				</label>
			</div>
			<div
				style={ {
					marginLeft: '1em',
				} }
			>
				<div
					style={ {
						display: 'flex',
						flexDirection: 'row',
						gap: '0.5em',
						marginTop: '5px',
					} }
				>
					<NumberControl
						id="nab-checker-alternative"
						min={ 0 }
						max={ maxCombinations - 1 }
						value={ newAlternative }
						disabled={ locked }
						onChange={ setNewAlternative }
					/>
					<button
						onClick={ onClick }
						disabled={ ! isDirty || locked }
					>
						Load
					</button>
				</div>
			</div>
		</div>
	);
}

function NumberControl( {
	id,
	value: inputValue,
	min,
	max,
	disabled,
	onChange,
}: {
	readonly id?: string;
	readonly value: number;
	readonly min: number;
	readonly max: number;
	readonly disabled?: boolean;
	readonly onChange: ( n: number ) => void;
} ): JSX.Element {
	const [ value, setValue ] = useState( `${ inputValue }` );
	useEffect( () => setValue( `${ inputValue }` ), [ inputValue ] );
	return (
		<input
			id={ id }
			style={ { width: '5em' } }
			type="number"
			min={ min }
			max={ max }
			value={ value }
			disabled={ disabled }
			onChange={ ( ev ) => {
				const newValue = ev.target.value;
				setValue( newValue );

				const newNumericValue = Number.parseInt( newValue );
				if ( min <= newNumericValue && newNumericValue <= max ) {
					onChange( newNumericValue );
				}
			} }
		/>
	);
}
