import {startTransition, useCallback, useEffect, useMemo, useRef, useState} from 'react';
import renderHtmlAttributes from "../../utils/renderHtmlAttributes";
import useFormSubmitSuccess from "../../hooks/useFormSubmitSuccess";
import jQuery from "jquery";
import "ion-rangeslider";
import type {IonRangeSliderOptions} from "ion-rangeslider";
import type {FreemiusProps} from "../../types/freemius";
import UpgradeOverlay from "../../components/UpgradeOverlay";

type FieldProps = {
	itemId: string
	attrs: Record<string, string | string[]>
	min: IonRangeSliderOptions['min']
	max: IonRangeSliderOptions['max']
	step: IonRangeSliderOptions['step']
	type: IonRangeSliderOptions['type']
	skin: IonRangeSliderOptions['skin']
	from: IonRangeSliderOptions['from']
	to: IonRangeSliderOptions['to']
	grid: boolean
	grid_snap: boolean
	grid_num: number
	hide_min_max: boolean
	hide_from_to: boolean
	prefix: string
	postfix: string
	max_postfix: string
	show_input: boolean
} & FreemiusProps

const Field = (props: FieldProps) => {

	const inputRef = useRef<HTMLInputElement | null>(null);
	const instance = useRef<any>(null);
	const attrs = useMemo(() => renderHtmlAttributes(props.attrs), [props.attrs]);

	const [fromValue, setFromValue] = useState<string>(String(props.from));
	const [toValue, setToValue] = useState<string>(String(props.to));

	// Reset after form submit
	useFormSubmitSuccess(inputRef, () => {
		setFromValue(String(props.from));
		setToValue(String(props.to));
		instance.current?.update({
			from: props.from,
			to: props.to
		});
	}, [props.from, props.to]);

	const updateInputs = useCallback((data: any) => {
		const from = data.from;
		const to = data.to;
		setFromValue(String(from));
		setToValue(String(to));
	}, []);

	useEffect(() => {
		const element = jQuery(inputRef.current as unknown as HTMLInputElement);
		if (!element) {
			return;
		}
		element.ionRangeSlider({
			skin: props.skin,
			type: props.type,
			min: props.min,
			max: props.max,
			step: props.step,
			from: props.from,
			to: props.to,
			keyboard: true,
			grid: props.grid,
			grid_snap: props.grid_snap,
			grid_num: props.grid_num,
			hide_min_max: props.hide_min_max,
			hide_from_to: props.hide_from_to,
			prefix: props.prefix,
			postfix: props.postfix,
			max_postfix: props.max_postfix,
			onStart: updateInputs,
			onChange: updateInputs,
			onFinish: updateInputs,
			input_values_separator: ',',
			disable: !props.freemius.can_use_premium_code
		});
		instance.current = element.data("ionRangeSlider");
		return () => {
			instance.current?.destroy();
		}
	}, [props.freemius.can_use_premium_code, props.from, props.grid, props.grid_num, props.grid_snap, props.hide_from_to, props.hide_min_max, props.max, props.max_postfix, props.min, props.postfix, props.prefix, props.skin, props.step, props.to, props.type, updateInputs]);

	const fromValidate = useCallback((val: string) => {
		let numVal = Number(val);
		const min = Number(props.min);
		const max = Number(props.max);
		if (props.type === 'double') {
			const to = Number(toValue);
			if (numVal < min) {
				numVal = min;
			} else if (numVal > to) {
				numVal = to;
			}
		} else if (numVal < min) {
			numVal = min;
		} else if (numVal > max) {
			numVal = max
		}
		return numVal;
	}, [props.max, props.min, props.type, toValue]);

	const toValidate = useCallback((val: string) => {
		let numVal = Number(val);
		const max = Number(props.max);
		const from = Number(fromValue);
		if (numVal < from) {
			numVal = from;
		} else if (numVal > max) {
			numVal = max;
		}
		return numVal;
	}, [fromValue, props.max]);

	const fromMax = useMemo(() => {
		return props.type === 'double' ? toValue : props.max;
	}, [props.max, props.type, toValue]);

	useEffect(() => {
		const element = inputRef.current;
		element?.dispatchEvent(new Event('change', {bubbles: true}));
	}, [fromValue, toValue]);

	return (
		<>
			{!props.freemius.can_use_premium_code && <UpgradeOverlay url={props.freemius.get_upgrade_url}/>}
			<div data-type={props.type} className="hulk-slider-field-wrap">
				<div className="hulk-slider-field">
					<input ref={inputRef} type="hidden" {...attrs}/>
				</div>
				{props.show_input && (
					<div className="hulk-slider-input">
						<div className="hulk-slider-from-input">
							<input
								type="number"
								value={fromValue}
								onChange={event => {
									if (!props.freemius.can_use_premium_code) {
										return;
									}
									const val = event.target.value;
									setFromValue(val);
									startTransition(() => {
										instance.current?.update({
											from: fromValidate(val)
										});
									});
								}}
								onBlur={event => {
									setFromValue(String(fromValidate(event.target.value)));
								}}
								min={props.min}
								max={fromMax}
								step={props.step}
								className={'elementor-field elementor-field-textual hulk-show-input'}
							/>
						</div>
						{props.type === 'double' && (
							<>
								<div className="hulk-slider-input-separator"></div>
								<div className="hulk-slider-to-input">
									<input
										type="number"
										value={toValue}
										onChange={event => {
											if (!props.freemius.can_use_premium_code) {
												return;
											}
											const val = event.target.value;
											setToValue(val);
											startTransition(() => {
												instance.current?.update({
													to: toValidate(val)
												});
											});
										}}
										onBlur={event => {
											setToValue(String(toValidate(event.target.value)));
										}}
										min={fromValue}
										max={props.max}
										step={props.step}
										className={'elementor-field elementor-field-textual hulk-show-input'}
									/>
								</div>
							</>
						)}
					</div>
				)}
			</div>
		</>
	);
};

export default Field;
