import "intl-tel-input/dist/css/intlTelInput.min.css";
import React, {startTransition, useCallback, useEffect, useMemo, useRef, useState} from 'react';
import IntlTelInput, {IntlTelInputRef} from 'intl-tel-input/reactWithUtils';
import use from '../utils/use';
import isEditMode from "../utils/isEditMode";
import geoIpLookup from "../utils/geoIpLookup";
import {FieldProps} from "./Field";
import fetchTranslation from "../utils/fetchTranslation";
import replaceAll from "../utils/replaceAll";
import getErrorKeyByCode from "../utils/getErrorKeyByCode";
import errorMessages from "../utils/errorMessages";
import useError from "../hooks/useError";
import FullPhoneInput from "./components/FullPhoneInput";
import type {Iso2} from "intl-tel-input/data";

const IntlTelInputLazy = (props: FieldProps) => {

	const intlTelRef = useRef<IntlTelInputRef | null>(null);
	const [value, setValue] = useState(props.value);
	const [isValid, setIsValid] = useState(false);
	const [errorCode, setErrorCode] = useState<number | null>(null);
	const [error, setError] = useState('');

	const getI18n = useMemo(() => {
		if (props.internationalisation !== 'en') {
			return use(fetchTranslation(props.internationalisation));
		}
		return undefined;
	}, [props.internationalisation]);

	const geoIpLookupCode: string = useMemo(() => {
		if (props.autoCountry) {
			return use(geoIpLookup(props.initialCountry));
		}
		return '';
	}, [props.autoCountry, props.initialCountry]);

	const geoIpLookupCallback = useCallback((callback: any) => {
		if (props.autoCountry && geoIpLookupCode) {
			return callback(geoIpLookupCode)
		}
		return null;
	}, [geoIpLookupCode, props.autoCountry]);

	function validateOnBlur() {
		if (!props.enableValidation || errorCode === null || errorCode === undefined) {
			return;
		}
		const key = getErrorKeyByCode(errorCode);
		// @ts-ignore
		const message = (props.customMessages && props?.[key]) ? props?.[key] : errorMessages?.[key];
		if (!message || value.trim() === '') {
			return;
		}
		setError(message);
	}

	// Error clear if number is valid
	useEffect(() => {
		startTransition(() => {
			if (value.trim() === '') {
				setError('');
			} else if (isValid) {
				setError('');
			}
		});
	}, [isValid, value]);

	// Append error element
	useError(error, props.enableValidation, intlTelRef);

	// Reset
	useEffect(() => {
		const inputElement = intlTelRef.current?.getInput();
		if (!inputElement) {
			return;
		}
		const formElement = jQuery(inputElement).closest('.elementor-form');

		function handler() {
			setValue(props.value);
		}

		formElement.on('submit_success.hulk_epfitf', handler);
		return () => {
			formElement.off('submit_success.hulk_epfitf', handler);
		}
	}, [props.value]);

	const onlyCountries = useMemo(() => {
		if (props.autoCountry && props.onlyCountries.length > 0) {
			const found = props.onlyCountries.some(value1 => value1 === geoIpLookupCode);
			if (!found) {
				props.onlyCountries.unshift(geoIpLookupCode as Iso2);
			}
		}
		return props.onlyCountries;
	}, [geoIpLookupCode, props.autoCountry, props.onlyCountries]);

	const excludeCountries = useMemo(() => {
		if (props.autoCountry) {
			return props.excludeCountries.filter(value1 => value1 !== geoIpLookupCode);
		}
		return props.excludeCountries;
	}, [geoIpLookupCode, props.autoCountry, props.excludeCountries]);

	return (
		<>
			<IntlTelInput
				ref={intlTelRef}
				value={value}
				onChangeNumber={setValue}
				onChangeValidity={setIsValid}
				onChangeErrorCode={setErrorCode}
				inputProps={{
					id: `${props.id}-telephone`,
					name: props.name,
					className: props.class,
					onBlur: validateOnBlur,
					required: props.required,
				}}
				initialCountry={props.autoCountry ? 'auto' : props.initialCountry}
				strictMode={props.strictMode}
				{...((props?.countryOrder && props.countryOrder.length > 0) && {
					countryOrder: props.countryOrder,
				})}
				onlyCountries={onlyCountries}
				excludeCountries={excludeCountries}
				nationalMode={props.nationalMode}
				showFlags={props.showFlags}
				separateDialCode={props.separateDialCode}
				countrySearch={true} // Show country search input inside dropdown
				allowDropdown={true} // Show dropdown
				fixDropdownWidth={true}
				allowedNumberTypes={['MOBILE']}
				placeholderNumberType={'MOBILE'}
				dropdownContainer={props.formElement}
				{...(props.placeholder && {
					customPlaceholder: (selectedCountryPlaceholder: string) => {
						return replaceAll(props.placeholder, '{{country}}', selectedCountryPlaceholder);
					}
				})}
				{...(isEditMode && {useFullscreenPopup: false})}
				{...((props.autoCountry && geoIpLookupCode) && {geoIpLookup: geoIpLookupCallback})}
				countryNameLocale={props.internationalisation || 'en'}
				i18n={getI18n}
			/>
			{props.fullPhone && (
				<FullPhoneInput
					intlTelRef={intlTelRef}
					custom_id={props.custom_id}
					watchValue={value}
				/>
			)}
			<input
				type="hidden"
				name={`form_fields[${props.custom_id}_isValid]`}
				defaultValue={String(isValid)}
			/>
			<input
				type="hidden"
				name={`form_fields[${props.custom_id}_errorCode]`}
				defaultValue={errorCode || 0}
			/>
			<div id={props.id}/>
		</>
	);
};

export default IntlTelInputLazy;
