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

import { useNavigate } from 'react-router-dom';

import type { NavMenuItem } from '@/utils/navUtils';

const OVERFLOW_BUTTON_WIDTH = 80;
const MENU_ITEM_GAP = 10;

interface UseActionParams {
    menuItems: NavMenuItem[];
    isMobile: boolean;
    isLoggedIn: boolean;
}

/**
 * Topbar UI 交互响应逻辑 Hook
 * 处理 UI 状态、事件处理、DOM 交互等响应逻辑
 */
export function useAction({ menuItems, isMobile, isLoggedIn }: UseActionParams) {
    const navigate = useNavigate();
    const menuContainerRef = useRef<HTMLDivElement>(null);
    const menuItemsRef = useRef<Map<string, HTMLButtonElement>>(new Map());
    const itemWidthCache = useRef<Map<string, number>>(new Map());
    const loginButtonRef = useRef<HTMLButtonElement>(null);
    const languageButtonRef = useRef<HTMLDivElement>(null);
    const [isMobileMenuOpen, setIsMobileMenuOpen] = useState(false);
    const [isMobileMenuClosing, setIsMobileMenuClosing] = useState(false);
    const [isOverflowMenuOpen, setIsOverflowMenuOpen] = useState(false);
    const [visibleMenuItems, setVisibleMenuItems] = useState<NavMenuItem[]>(() => menuItems);
    const [overflowMenuItems, setOverflowMenuItems] = useState<NavMenuItem[]>([]);

    const calculateVisibleItems = useCallback(() => {
        if (isMobile || !menuContainerRef.current || menuItems.length === 0) {
            setVisibleMenuItems(menuItems);
            setOverflowMenuItems([]);
            return;
        }

        const container = menuContainerRef.current;
        const loginBtnWidth = loginButtonRef.current
            ? loginButtonRef.current.offsetWidth + MENU_ITEM_GAP
            : 0;
        const langBtnWidth = languageButtonRef.current
            ? languageButtonRef.current.offsetWidth + MENU_ITEM_GAP
            : 0;
        const containerWidth = container.offsetWidth - loginBtnWidth - langBtnWidth;

        let totalWidth = 0;
        const visible: NavMenuItem[] = [];
        const overflow: NavMenuItem[] = [];

        for (let i = 0; i < menuItems.length; i++) {
            const item = menuItems[i];
            const itemElement = menuItemsRef.current.get(item.name);

            let itemWidth: number | undefined;
            if (itemElement) {
                itemWidth = itemElement.offsetWidth + MENU_ITEM_GAP;
                itemWidthCache.current.set(item.name, itemWidth);
            } else {
                itemWidth = itemWidthCache.current.get(item.name);
            }

            if (itemWidth === undefined) {
                visible.push(item);
                continue;
            }

            const needsOverflowButton = i < menuItems.length - 1;
            if (
                totalWidth + itemWidth + (needsOverflowButton ? OVERFLOW_BUTTON_WIDTH : 0) <=
                containerWidth
            ) {
                visible.push(item);
                totalWidth += itemWidth;
            } else {
                overflow.push(...menuItems.slice(i));
                break;
            }
        }

        setVisibleMenuItems(visible);
        setOverflowMenuItems(overflow);
        // eslint-disable-next-line react-hooks/exhaustive-deps
    }, [isMobile, menuItems, isLoggedIn]);

    useEffect(() => {
        if (!isMobile && menuItems.length > 0) {
            const rafId = requestAnimationFrame(() => {
                calculateVisibleItems();
            });
            return () => cancelAnimationFrame(rafId);
        }
    }, [isMobile, menuItems.length, isLoggedIn, calculateVisibleItems]);

    useEffect(() => {
        if (isMobile) {
            return;
        }

        const handleResize = () => {
            calculateVisibleItems();
        };

        window.addEventListener('resize', handleResize);
        return () => window.removeEventListener('resize', handleResize);
    }, [isMobile, calculateVisibleItems]);

    const handleMenuClick = useCallback(
        (path: string) => {
            navigate(path);
            setIsMobileMenuOpen(false);
            setIsOverflowMenuOpen(false);
        },
        [navigate]
    );

    const toggleMobileMenu = useCallback(() => {
        if (isMobileMenuOpen) {
            setIsMobileMenuClosing(true);
        } else {
            setIsMobileMenuOpen(true);
            setIsMobileMenuClosing(false);
        }
    }, [isMobileMenuOpen]);

    const closeMobileMenu = useCallback(() => {
        setIsMobileMenuClosing(true);
    }, []);

    const handleMenuAnimationEnd = useCallback(() => {
        if (isMobileMenuClosing) {
            setIsMobileMenuOpen(false);
            setIsMobileMenuClosing(false);
        }
    }, [isMobileMenuClosing]);

    const setOverflowMenuOpen = useCallback((open: boolean) => {
        setIsOverflowMenuOpen(open);
    }, []);

    const setMenuItemRef = useCallback((itemName: string) => {
        return (el: HTMLButtonElement | null) => {
            if (el) {
                menuItemsRef.current.set(itemName, el);
            } else {
                menuItemsRef.current.delete(itemName);
            }
        };
    }, []);

    return {
        menuContainerRef,
        loginButtonRef,
        languageButtonRef,
        menuItemsRef,
        isMobileMenuOpen,
        isMobileMenuClosing,
        isOverflowMenuOpen,
        visibleMenuItems,
        overflowMenuItems,
        handleMenuClick,
        toggleMobileMenu,
        closeMobileMenu,
        handleMenuAnimationEnd,
        setOverflowMenuOpen,
        setMenuItemRef,
    };
}
