import { useDebounce } from "@uidotdev/usehooks";
import { AnimatePresence, motion } from "framer-motion";
import { useCallback, useEffect, useState } from "react";
import { useDispatch, useSelector } from "react-redux";

import { MIcon } from "@components/common/MIcon";
import type { SelectItem } from "@components/common/Select";
import { useTheme } from "@hooks/useTheme";
import { setSlippage, toggleDynamicSlippage } from "@store/settingsSlice";
import type { ReduxStateType } from "@store/types";
import { getBorderRadius } from "@utils/getBorderRadius";
import { SettingsItem } from "../SettingsItem";

const slippageOptions: SelectItem[] = [
	{
		id: "dynamic",
		label: "suggested",
	},
	{
		id: "0.5",
		label: "0.5%",
	},
	{
		id: "1",
		label: "1%",
	},
];

export const Slippage = () => {
	const dispatch = useDispatch();
	const theme = useTheme();
	const currentSlippageId = useSelector(
		(state: ReduxStateType) => state.settings.slippage,
	);
	const currentSlippageItem = slippageOptions.filter(
		(item) => item.id === currentSlippageId,
	)[0];

	const setItem = useCallback(
		(_value: string) => {
			const isDynamic = _value === "dynamic";
			dispatch(toggleDynamicSlippage(isDynamic));
			dispatch(setSlippage(_value));
		},
		[dispatch],
	);

	const [showDropdown, toggleDropdown] = useState<boolean>(false);
	const [inputValue, setInputValue] = useState<number>();

	const debouncedValue = useDebounce(inputValue, 300);

	useEffect(() => {
		if (debouncedValue) setItem(debouncedValue?.toString());
	}, [debouncedValue, setItem]);

	function setValue(_value: number) {
		if (_value <= 50) setInputValue(_value);
	}

	useEffect(() => {
		const _isCustomValue =
			currentSlippageId !== "dynamic" &&
			currentSlippageId !== "0.5" &&
			currentSlippageId !== "1";

		if (_isCustomValue) {
			setInputValue(Number(currentSlippageId));
		} else setInputValue(undefined);
	}, [currentSlippageId]);

	return (
		<div className="bn-relative bn-mb-4">
			<SettingsItem
				label="Slippage Tolerance"
				key="slippage-tolerance"
				icon="surfing"
			>
				<button
					type="button"
					onClick={() => toggleDropdown(!showDropdown)}
					className="bn-text-secondary bn-text-base bn-font-medium bn-border-none bn-bg-transparent bn-capitalize bn-flex bn-items-center bn-p-0 bn-cursor-pointer"
				>
					{/* biome-ignore format: */}
					<span className="bn-pr-[5px]">{currentSlippageItem?.label || `${currentSlippageId}%`}</span>
					{/* biome-ignore format:  */}
					<MIcon classNames={`bn-text-primary ${showDropdown ? 'bn-rotate-180' : ''}`} name="keyboard_arrow_down" />
				</button>
			</SettingsItem>
			<AnimatePresence>
				{showDropdown && (
					<motion.div
						initial={{ opacity: 0, maxHeight: 0 }}
						animate={{ opacity: 1, maxHeight: 200 }}
						className="bn-px-2 bn-py-1.5 bn-bg-layer-2 bn-rounded-lg bn-flex bn-space-x-1 bn-items-center bn-justify-normal overflow-hidden"
						transition={{ duration: 0.1, ease: "easeInOut" }}
					>
						{slippageOptions.map((item) => {
							return (
								<SlippageButton
									key={item.id}
									label={item.label}
									active={currentSlippageId === item.id}
									onClick={() => {
										setItem(item.id);
									}}
								/>
							);
						})}
						<div
							className="bn-bg-layer-3 bn-px-2.5 bn-flex bn-items-center bn-justify-between bn-w-[134px] bn-h-[30px] bn-text-sm bn-font-semibold bn-text-secondary"
							style={{ borderRadius: getBorderRadius(theme.borderRadius, 8) }}
						>
							<label htmlFor="bungee-custom-slippage-input">Custom</label>
							<input
								className="bn-bg-transparent bn-px-1 bn-border-0 bn-w-[51px] bn-text-primary bn-text-sm bn-text-right"
								type="number"
								value={inputValue ?? ""}
								onChange={(e) => setValue(Number(e.target.value))}
								id="bungee-custom-slippage-input"
							/>
							<span>%</span>
						</div>
					</motion.div>
				)}
			</AnimatePresence>
		</div>
	);
};

const SlippageButton = ({
	label,
	onClick,
	active = false,
}: { label: string; onClick: () => void; active?: boolean }) => {
	const theme = useTheme();

	// @fixme: hardcoding text color for active variant
	// biome-ignore format:
	const style = `bn-text-sm bn-cursor-pointer bn-font-semibold bn-border-0 bn-capitalize bn-h-[30px] ${active ? 'bn-bg-theme bn-text-[#262420]' : 'bn-text-primary bn-bg-transparent'} ${label === 'suggested' ? 'bn-flex-1' : 'bn-w-[64px]'}`
	return (
		<button
			type="button"
			className={style}
			style={{ borderRadius: getBorderRadius(theme.borderRadius, 8) }}
			onClick={onClick}
		>
			{label}
		</button>
	);
};
