import { useEffect, useState } from 'react';
import Button from '@mui/material/Button';
import Stack from '@mui/material/Stack';
import { parsePhoneNumber } from 'awesome-phonenumber';
import LoopIcon from '@mui/icons-material/Loop';

import type { AsYouType, PhoneNumber } from 'awesome-phonenumber';
import type { OutlinedTextFieldProps } from '@mui/material/TextField';

import CodeInput from './CodeInput';
import PhoneInput, { formatter, formatPhoneNumber } from './PhoneInput';
import CountrySelector from './CountrySelector';
import { useSendMagicLink, useVerifyMagicLink, useWidget } from 'hooks';
import { LoadingButton } from 'components';

export interface PhoneFormProps
	extends Omit<OutlinedTextFieldProps, 'variant'> {
	icon?: boolean | React.ReactNode;
}

const PhoneForm = (props: PhoneFormProps) => {
	const { children, icon } = props;

	const { flow = 'sms', goTo, loginHint } = useWidget();

	const { mutate: verifyMagicLink, isLoading: verifyingMagicLink } =
		useVerifyMagicLink();

	const [country, setCountry] = useState('US');
	const [formattedPhoneNumber, setFormattedPhoneNumber] =
		useState<string>('');
	const [phoneNumber, setPhoneNumber] = useState<PhoneNumber>();
	const [_formatter, createFormatter] = useState<AsYouType | undefined>();
	const [mfaCode, setMfaCode] = useState('');
	const [isCodeInput, setIsCodeInput] = useState(flow === 'sms-verify');
	const [errorText, setErrorText] = useState<string | undefined>();
	const [isError, setIsError] = useState<boolean>(false);

	const { mutate: sendMagicLink, isLoading: sendingMagicLink } =
		useSendMagicLink({ onSettled: () => setIsCodeInput(() => true) });

	useEffect(() => {
		if (country) {
			createFormatter(() => formatter(country));
		}
	}, [country]);

	useEffect(() => {
		if (!formattedPhoneNumber && loginHint && country) {
			setPhoneNumber(parsePhoneNumber(loginHint, country));
		}
	}, [loginHint]);

	const validateInput = (allowBlank: boolean = false) => {
		if (!phoneNumber && !allowBlank) {
			setErrorText('Please enter your phone number');
			setIsError(true);
		} else {
			setErrorText('');
			setIsError(false);
		}
	};

	const onChangeNumber: React.ChangeEventHandler<HTMLInputElement> = (
		event
	) => {
		const { data } = event?.nativeEvent as CompositionEvent;

		const value = data || event?.target?.value;

		if (_formatter) {
			const formattedNumber = formatPhoneNumber(_formatter, value);

			const number = _formatter.getPhoneNumber();

			setPhoneNumber(number);

			if (formattedNumber || formattedNumber === '') {
				validateInput();
				setFormattedPhoneNumber(formattedNumber);
			}
		}
	};

	const onChangeCode = (event: { target: { value: any } }) =>
		setMfaCode(event.target.value);

	const onSelect = (event: { target: { value: any } }) =>
		setCountry(event.target.value);

	const onBlur = () => validateInput(true);

	const onKeyPress: React.KeyboardEventHandler<HTMLDivElement> = ({
		key,
	}) => {
		if (key === 'Enter') {
			handleSend();
		}
	};

	const handleSend = () => {
		if (!isError && phoneNumber) {
			const {
				number: { e164 },
				valid,
			} = phoneNumber.toJSON();

			if (!valid) {
				setErrorText('Phone number is not valid!');
				setIsError(true);
			} else if (e164) {
				sendMagicLink({ phoneNumber: e164 });
			}
		}

		if (!phoneNumber) {
			setErrorText('Please enter a phone number');
			setIsError(true);
		}
	};

	const handleVerify = () => {
		const {
			number: { e164 },
		} = phoneNumber?.toJSON();

		if (!isError && mfaCode && mfaCode !== '' && e164) {
			verifyMagicLink({ code: mfaCode, phone: e164 });
		}
	};

	return (
		<>
			<Stack sx={{ width: '100%' }}>
				{!isCodeInput && (
					<CountrySelector onChange={onSelect} value={country} />
				)}
				<PhoneInput
					onChange={onChangeNumber}
					value={formattedPhoneNumber}
					disabled={isCodeInput}
					helperText={errorText}
					error={!!errorText}
					{...{ icon, onBlur, onKeyPress }}
				/>
				{isCodeInput && (
					<CodeInput onChange={onChangeCode} value={mfaCode} />
				)}
			</Stack>
			<Stack spacing={2} sx={{ width: '100%' }}>
				<LoadingButton
					variant='primary'
					disabled={sendingMagicLink || verifyingMagicLink}
					loading={
						isCodeInput ? verifyingMagicLink : sendingMagicLink
					}
					onClick={() =>
						isCodeInput ? handleVerify() : handleSend()
					}
				>
					Continue
				</LoadingButton>
				{isCodeInput ? (
					<>
						<LoadingButton
							variant='secondary'
							disabled={sendingMagicLink || verifyingMagicLink}
							loading={sendingMagicLink}
							endIcon={<LoopIcon />}
						>
							Resend
						</LoadingButton>
						<Button
							variant='text'
							disableFocusRipple
							disableTouchRipple
							size='small'
							component='a'
							onClick={() => goTo('sms')}
							sx={{ m: 0, p: 0 }}
						>
							Start over
						</Button>
					</>
				) : (
					children
				)}
			</Stack>
		</>
	);
};

export default PhoneForm;
