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

import { yieldMainThread } from "@devowl-wp/react-utils";
import { extendBannerBubbleStylesheet } from "@devowl-wp/web-cookie-banner";

import { BannerStickyIcon } from "./icon.js";
import { useBanner } from "../../../contexts/banner.js";
import { useBannerStylesheet } from "../../../hooks/banner/useBannerStylesheet.js";
import { AnimatedCss } from "../../animateCss.js";
import { AsciiSpinner } from "../../asciiSpinner.js";

import type { FC } from "react";

const BannerStickyBubble: FC = () => {
    const {
        sticky: { icon, iconCustom, iconCustomRetina, animationsEnabled, hoverIconCustom, hoverIconCustomRetina },
        texts: { stickyChange, stickyHistory, stickyRevoke, stickyRevokeSuccessMessage },
        openBanner,
        openHistory,
        revokeConsent,
        previewStickyMenuOpenState = false,
    } = useBanner();
    const { bubble, bubbleActive, bubbleMounted, menu, specify, className, screenReaderOnlyClass } =
        useBannerStylesheet().extend(...extendBannerBubbleStylesheet);
    specify(className);
    const [isActive, setIsActive] = useState(false);
    const [isHover, setIsHover] = useState(false);
    const [renderedOnce, setRenderedOnce] = useState(false);
    const [isRevoked, setIsRevoked] = useState(false);
    const firstLinkRef = useRef<HTMLAnchorElement>();
    const useIsActive = isActive || previewStickyMenuOpenState;

    // Calculate logo
    const useRetina = iconCustomRetina && !iconCustom?.endsWith(".svg") && window.devicePixelRatio > 1;
    const useHoverRetina = hoverIconCustom && !hoverIconCustom?.endsWith(".svg") && window.devicePixelRatio > 1;
    const useIcon = useRetina ? iconCustomRetina : iconCustom;
    const useHoverIcon = useHoverRetina ? hoverIconCustomRetina : hoverIconCustom;

    useEffect(() => {
        if (previewStickyMenuOpenState && !renderedOnce) {
            setRenderedOnce(true);
        }
    }, [renderedOnce, previewStickyMenuOpenState]);

    const isScreenMountedRef = useRef(false);
    useEffect(() => {
        isScreenMountedRef.current = true;
    }, []);

    return (
        <div
            id={className}
            ref={(ref) => yieldMainThread().then(() => ref?.classList.add(bubbleMounted))}
            className={`${useIsActive ? bubbleActive : ""}`}
        >
            <a
                href="#"
                className={screenReaderOnlyClass}
                aria-label="focus"
                onFocus={(e) => {
                    // This element is used to focus the first link in the menu
                    setRenderedOnce(true);
                    e.target.style.display = "none"; // Hide from accessibility tree
                    yieldMainThread().then(() => firstLinkRef.current.focus());
                }}
            ></a>
            <div
                className={bubble}
                onClick={() => {
                    setIsActive(!isActive);
                    setRenderedOnce(true);
                }}
                onMouseEnter={() => setIsHover(true)}
                onMouseLeave={() => setIsHover(false)}
            >
                {icon === "custom" && useIcon && !useIsActive ? (
                    <img aria-hidden alt="icon" src={isHover ? useHoverIcon || useIcon : useIcon} />
                ) : (
                    <BannerStickyIcon type={useIsActive ? "close" : icon} />
                )}
            </div>
            <AnimatedCss
                animationIn="fadeInUp"
                animationInDuration={animationsEnabled ? 300 : 0}
                animationOut="fadeOutDown"
                animationOutDuration={animationsEnabled ? 300 : 0}
                isVisible={useIsActive}
                className={menu}
                style={{ display: renderedOnce || previewStickyMenuOpenState ? undefined : "none" }}
            >
                {renderedOnce && (
                    <ul>
                        {!!stickyHistory && (
                            <li>
                                <a
                                    href="#b"
                                    ref={firstLinkRef}
                                    onClick={(e) => {
                                        openHistory(e as any);
                                        setIsActive(false);
                                    }}
                                >
                                    {stickyHistory}
                                </a>
                            </li>
                        )}
                        {!!stickyRevoke && (
                            <li>
                                <a
                                    href="#a"
                                    onClick={(e) => {
                                        revokeConsent(stickyRevokeSuccessMessage, e as any);
                                        setIsRevoked(true);
                                    }}
                                >
                                    {stickyRevoke}
                                    {isRevoked && (
                                        <Fragment>
                                            &nbsp;
                                            <AsciiSpinner />
                                        </Fragment>
                                    )}
                                </a>
                            </li>
                        )}
                        {!!stickyChange && (
                            <li>
                                <a
                                    href="#c"
                                    onClick={(e) => {
                                        openBanner(e as any);
                                        setIsActive(false);
                                    }}
                                >
                                    {stickyChange}
                                </a>
                            </li>
                        )}
                    </ul>
                )}
            </AnimatedCss>
        </div>
    );
};

export { BannerStickyBubble };
