// 在线名单徽章即时提示工具，负责动态徽章的悬浮气泡定位和显示。

const TOOLTIP_SELECTOR = ".user-badge-icon[data-instant-tooltip]";

/**
 * 绑定在线名单徽章的即时悬浮提示。
 * Vite 模块脚本通常晚于 Blade 经典脚本执行，这里由模块加载后主动绑定，避免依赖 Blade 调用时序。
 *
 * @param {HTMLElement|null} tooltip 提示气泡容器
 * @param {Document|HTMLElement} root 事件委托根节点
 * @returns {{hide: () => void, destroy: () => void}|null}
 */
export function bindInstantHoverTooltip(
    tooltip = document.getElementById("chat-hover-tooltip"),
    root = document,
) {
    if (!tooltip || tooltip.dataset.instantTooltipBound === "1") {
        return null;
    }

    tooltip.dataset.instantTooltipBound = "1";
    let activeTrigger = null;

    /**
     * 从事件目标解析可显示提示的徽章节点。
     *
     * @param {EventTarget|null} target 事件目标
     * @returns {HTMLElement|null}
     */
    const resolveTrigger = (target) => {
        if (!(target instanceof Element)) {
            return null;
        }

        return target.closest(TOOLTIP_SELECTOR);
    };

    /**
     * 把提示气泡定位到徽章旁边，同时避免超出视口边缘。
     *
     * @param {HTMLElement|null} trigger 当前悬浮徽章
     * @returns {void}
     */
    const position = (trigger) => {
        if (!trigger) {
            return;
        }

        const offset = 10;
        const rect = trigger.getBoundingClientRect();
        const tooltipWidth = tooltip.offsetWidth;
        const tooltipHeight = tooltip.offsetHeight;
        const fitsRight = rect.right + offset + tooltipWidth <= window.innerWidth - 8;
        const side = fitsRight ? "right" : "left";
        const nextLeft = fitsRight ? rect.right + offset : Math.max(8, rect.left - tooltipWidth - offset);
        const nextTop = Math.min(
            Math.max(8, rect.top + (rect.height - tooltipHeight) / 2),
            window.innerHeight - tooltipHeight - 8,
        );

        tooltip.dataset.side = side;
        tooltip.style.left = `${nextLeft}px`;
        tooltip.style.top = `${nextTop}px`;
    };

    /**
     * 显示当前徽章对应的提示文字。
     *
     * @param {HTMLElement|null} trigger 当前悬浮徽章
     * @returns {void}
     */
    const show = (trigger) => {
        const tooltipText = trigger?.dataset.instantTooltip || "";

        if (!trigger || !tooltipText) {
            return;
        }

        activeTrigger = trigger;
        tooltip.textContent = tooltipText;
        tooltip.style.display = "block";
        position(trigger);
    };

    /**
     * 隐藏提示气泡并清理方向状态。
     *
     * @returns {void}
     */
    const hide = () => {
        activeTrigger = null;
        tooltip.style.display = "none";
        tooltip.textContent = "";
        delete tooltip.dataset.side;
    };

    const handleMouseOver = (event) => {
        const trigger = resolveTrigger(event.target);

        if (trigger) {
            show(trigger);
        }
    };

    const handleMouseOut = (event) => {
        const trigger = resolveTrigger(event.target);

        if (!trigger || trigger !== activeTrigger) {
            return;
        }

        if (event.relatedTarget && trigger.contains(event.relatedTarget)) {
            return;
        }

        hide();
    };

    const reposition = () => {
        if (activeTrigger) {
            position(activeTrigger);
        }
    };

    root.addEventListener("mouseover", handleMouseOver);
    root.addEventListener("mouseout", handleMouseOut);
    window.addEventListener("scroll", reposition, true);
    window.addEventListener("resize", reposition);

    return {
        hide,
        destroy() {
            root.removeEventListener("mouseover", handleMouseOver);
            root.removeEventListener("mouseout", handleMouseOut);
            window.removeEventListener("scroll", reposition, true);
            window.removeEventListener("resize", reposition);
            delete tooltip.dataset.instantTooltipBound;
            hide();
        },
    };
}
