import { useCallback, useEffect, useRef, useState } from "react";

const useModal = (initialState?: boolean, bodyBlock = true) => {
	const [isOpen, setIsOpen] = useState(initialState || false);

	const toggleModal = useCallback(() => {
		setIsOpen((prev) => !prev);
	}, []);

	useEffect(() => {
		if (isOpen && bodyBlock) {
			if (!document.body.classList.contains("modal-open")) {
				document.body.classList.add("modal-open");
			}
		} else if (!isOpen && bodyBlock) {
			// Solo remover si no hay otros modales o FloatingPanels abiertos
			const hasOpenModals = document.querySelectorAll('[data-is-open="true"]').length > 0;
			if (!hasOpenModals) {
				document.body.classList.remove("modal-open");
			}
		}
	}, [isOpen, bodyBlock]);

	return {
		isOpen,
		toggleModal,
	};
};

const useModals = <T extends string>(modalKeys: readonly T[], bodyBlock = true) => {
	const [openModals, setOpenModals] = useState<Record<T, boolean>>(() =>
		modalKeys.reduce(
			(acc, key) => {
				acc[key] = false;
				return acc;
			},
			{} as Record<T, boolean>,
		),
	);

	const toggleModal = useCallback((modalKey: T) => {
		setOpenModals((prev) => ({ ...prev, [modalKey]: !prev[modalKey] }));
	}, []);

	const openModal = useCallback((modalKey: T) => {
		setOpenModals((prev) => ({ ...prev, [modalKey]: true }));
	}, []);

	const closeModal = useCallback((modalKey: T) => {
		setOpenModals((prev) => ({ ...prev, [modalKey]: false }));
	}, []);

	const isOpen = useCallback(
		(modalKey: T) => {
			return openModals[modalKey] || false;
		},
		[openModals],
	);

	useEffect(() => {
		const hasOpenModals = Object.values(openModals).some(Boolean);

		if (hasOpenModals && bodyBlock) {
			if (!document.body.classList.contains("modal-open")) {
				document.body.classList.add("modal-open");
			}
		} else if (!hasOpenModals) {
			// Solo remover si no hay otros modales o FloatingPanels abiertos
			const hasAnyOpenModals = document.querySelectorAll('[data-is-open="true"]').length > 0;
			if (!hasAnyOpenModals) {
				document.body.classList.remove("modal-open");
			}
		}
	}, [openModals, bodyBlock]);

	return {
		toggleModal,
		openModal,
		closeModal,
		isOpen,
	};
};

const useHandleClickOutside = (isOpen: boolean, handleClickOutside: (e: MouseEvent) => void) => {
	useEffect(() => {
		if (isOpen) {
			document.addEventListener("mousedown", handleClickOutside);
		} else {
			document.removeEventListener("mousedown", handleClickOutside);
		}

		return () => {
			document.removeEventListener("mousedown", handleClickOutside);
		};
	}, [isOpen, handleClickOutside]);
};

const useToast = () => {
	const [isVisible, setIsVisible] = useState(false);
	const [state, setState] = useState<any>(null);
	const timeoutRef = useRef<NodeJS.Timeout | null>(null);

	const toggleToast = useCallback((newState?: any) => {
		if (timeoutRef.current) {
			clearTimeout(timeoutRef.current);
		}

		if (newState) {
			setState(newState);
		}
		setIsVisible(true);

		timeoutRef.current = setTimeout(() => {
			setIsVisible(false);
		}, 6000);
	}, []);

	useEffect(() => {
		return () => {
			if (timeoutRef.current) {
				clearTimeout(timeoutRef.current);
			}
		};
	}, []);

	return { isVisible, setIsVisible, toggleToast, state };
};

export { useModal, useModals, useHandleClickOutside, useToast };
