import "intl-tel-input/styles";
import {startTransition, useEffect, useMemo, useRef, useState} from 'react';
import IntlTelInput, {type IntlTelInputRef} from "@intl-tel-input/react/with-utils";
import isEditMode from "../../utils/isEditMode";
import type {Iso2} from "intl-tel-input/data";
import type {FieldProps} from './Field';
import use from "../../utils/use";
import geoIpLookup from "./geoIpLookup";
import replaceAll from "../../utils/replaceAll.ts";
import FullPhoneInput from "./FullPhoneInput.tsx";
import fetchTranslation from "./fetchTranslation.ts";
import useError from "../../hooks/useError.ts";
import type {ValidationError} from "intl-tel-input";
import errorMessages from "./errorMessages.ts";

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

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

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

	function validateOnBlur() {
		if (!props.enableValidation || errorCode === null || errorCode === undefined) {
			return;
		}
		// @ts-ignore
		const message = (props.customMessages && props?.[errorCode]) ? props?.[errorCode] : errorMessages?.[errorCode];
		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_affef', handler);
		return () => {
			formElement.off('submit_success.hulk_affef', handler);
		}
	}, [props.value]);

	const onlyCountries = useMemo(() => {
		if (props.autoCountry && props.onlyCountries && 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 && props.excludeCountries !== null) {
			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 ? '' : props.initialCountry}
				strictMode={props.strictMode}
				{...((props?.countryOrder && props.countryOrder.length > 0) && {
					countryOrder: props.countryOrder,
				})}
				{...(props.nationalMode && {
					numberDisplayFormat: 'NATIONAL'
				})}
				onlyCountries={onlyCountries}
				excludeCountries={excludeCountries}
				showFlags={props.showFlags}
				separateDialCode={props.separateDialCode}
				countrySearch={true} // Show country search input inside dropdown
				countrySelectorMode={'AUTO'}
				allowedNumberTypes={['MOBILE']}
				placeholderNumberType={'MOBILE'}
				dropdownParent={props.formElement}
				{...(props.placeholder && {
					customPlaceholder: (selectedCountryPlaceholder: string) => {
						return replaceAll(props.placeholder, '{{country}}', selectedCountryPlaceholder);
					}
				})}
				{...(isEditMode && {useFullscreenPopup: false})}
				{...((props.autoCountry && geoIpLookupCode) && {
					initialCountryLookup: async () => geoIpLookupCode as Iso2
				})}
				countryNameLocale={props.internationalisation || 'en'}
				uiTranslations={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 TelInput;
