import Typography, { ETypo, ETypoColor } from "@Front/Components/DesignSystem/Typography";
import classes from "./classes.module.scss";
import { useRouter } from "next/router";
import React, { useCallback, useEffect } from "react";
import useHoverable from "@Front/Hooks/useHoverable";
import classNames from "classnames";
import { IAppRule } from "@Front/Api/Entities/rule";
import { ChevronDownIcon } from "@heroicons/react/24/outline";
import useOpenable from "@Front/Hooks/useOpenable";

type IProps = {
	item: IItem;
};

type IItemBase = {
	text: string;
	icon?: JSX.Element;
	hasSeparator?: boolean;
	color?: ETypoColor;
	onClose?: () => void;
};

type IItemWithLink = IItemBase & {
	link: string;
	rules?: IAppRule[];
	routesActive?: string[];
	onClick?: never;
	dropdown?: never;
	target?: "_blank";
};

type IItemWithOnClick = IItemBase & {
	onClick: () => void;
	link?: never;
	rules?: never;
	routesActive?: never;
	dropdown?: never;
	target?: never;
};

type IItemWithDropdown = IItemBase & {
	dropdown: {
		items: IItem[];
	};
	routesActive?: never;
	link?: never;
	rules?: never;
	onClick?: never;
	target?: never;
};

export type IItem = IItemWithLink | IItemWithOnClick | IItemWithDropdown;

export default function MenuItem(props: IProps) {
	const { item } = props;
	const router = useRouter();
	const { pathname } = router;
	const [isActive, setIsActive] = React.useState(item.link === pathname);

	const { isOpen, toggle, open } = useOpenable();

	const handleClickElement = useCallback(
		(e: React.MouseEvent<HTMLDivElement>) => {
			item.onClose?.();
			const link = e.currentTarget.getAttribute("data-link");
			if (item.target === "_blank") window.open(item.link, "_blank");
			if (link) router.push(link);
			if (item.onClick) item.onClick();
		},
		[item, router],
	);

	const { handleMouseEnter, handleMouseLeave, isHovered } = useHoverable();

	const getColor = useCallback(() => {
		if (isActive) return ETypoColor.CONTRAST_ACTIVED;
		if (isHovered && item.color !== ETypoColor.ERROR_WEAK_CONTRAST) return ETypoColor.CONTRAST_HOVERED;
		if (item.color) return item.color;
		if (isHovered) return ETypoColor.CONTRAST_DEFAULT;
		return ETypoColor.CONTRAST_DEFAULT;
	}, [isActive, isHovered, item.color]);

	useEffect(() => {
		if (item.link === pathname) setIsActive(true);
		if (item.routesActive) {
			for (const routeActive of item.routesActive) {
				if (isActive) break;
				if (pathname.includes(routeActive)) setIsActive(true);
			}
		}
		if (item.dropdown) {
			for (const subItem of item.dropdown.items) {
				if (isActive) break;
				if (subItem.link === pathname) {
					!isOpen && open();
					setIsActive(true);
				}
				if (subItem.routesActive) {
					for (const routeActive of subItem.routesActive) {
						if (isActive) break;
						if (pathname.includes(routeActive)) {
							!isOpen && open();
							setIsActive(true);
						}
					}
				}
			}
		}
	}, [isActive, isOpen, item.dropdown, item.link, item.routesActive, open, pathname]);

	return (
		<div
			className={classNames(classes["root"], isActive && classes["active"])}
			onClick={handleClickElement}
			data-link={item.link}
			onMouseEnter={handleMouseEnter}
			onMouseLeave={handleMouseLeave}>
			<div className={classes["menu-item"]} onClick={item.dropdown && toggle}>
				{item.icon && React.cloneElement(item.icon, { color: `var(${getColor()})` })}
				<Typography typo={ETypo.TEXT_LG_REGULAR} color={getColor()}>
					{item.text}
				</Typography>
				{item.dropdown &&
					React.cloneElement(<ChevronDownIcon className={classNames(classes["chevron"], isOpen && [classes["open"]])} />, {
						color: `var(${getColor()})`,
					})}
			</div>
			{item.dropdown && (
				<div className={classNames(classes["dropdown"], isOpen && [classes["open"]])}>
					{item.dropdown.items.map((subItem, index) => (
						<MenuItem key={index} item={subItem} />
					))}
				</div>
			)}
			{item.hasSeparator && <div className={classes["separator"]} />}
		</div>
	);
}
