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

import { yieldLazyLoad, yieldMainThread } from "@devowl-wp/react-utils";
import { extendBannerContentStylesheet, extendCommonButtonsStylesheet, fastdom } from "@devowl-wp/web-cookie-banner";

import { BannerBody } from "./body.js";
import { useBanner } from "../../../contexts/banner.js";
import { useBannerStylesheet } from "../../../hooks/banner/useBannerStylesheet.js";
import { BannerFooter } from "../footer/footer.js";
import { BannerHeader } from "../header/header.js";

import type { FC } from "react";

const YieldBannerHeader = yieldLazyLoad(Promise.resolve(BannerHeader), "BannerHeader");
const YieldBannerBody = yieldLazyLoad(Promise.resolve(BannerBody), "BannerBody");
const YieldBannerFooter = yieldLazyLoad(Promise.resolve(BannerFooter), "BannerFooter");

const BannerContent: FC = () => {
    const {
        Content,
        hideOnMobileClass,
        dimsContent,
        dimsOverlay,
        dimsHeader,
        dimsFooter,
        dimsRightSidebar,
        A11ySkipToLink,
        a11yIds: { firstButton },
    } = useBannerStylesheet()
        .extend(...extendCommonButtonsStylesheet)
        .extend(...extendBannerContentStylesheet);

    const {
        set,
        decision: { acceptAll, acceptEssentials, showCloseIcon },
        mobile,
        individualPrivacyOpen,
        bodyDesign: { acceptEssentialsUseAcceptAll },
        activeAction,
        pageRequestUuid4,
        i18n: { skipToConsentChoices },
    } = useBanner();
    const ref = useRef<HTMLDivElement>();
    const useAcceptEssentials =
        acceptEssentialsUseAcceptAll && acceptAll === acceptEssentials ? acceptAll : acceptEssentials;

    const headerClassName =
        mobile.hideHeader &&
        !activeAction &&
        !individualPrivacyOpen &&
        (useAcceptEssentials === "hide" ? !showCloseIcon : true)
            ? hideOnMobileClass
            : "";

    // As we use `<Suspense` components we cannot use `useEffect` as `ref.current` is `null`
    const dimsDisposer = useRef<Record<string, () => void>>();
    dimsDisposer.current = dimsDisposer.current || {};
    const getDimsDependencies = useCallback(
        () => [document.querySelector(`#${pageRequestUuid4} div[class*="animate__"]`) as HTMLElement],
        [pageRequestUuid4],
    );
    const updateRefDims = useCallback(
        ([observer, , disconnect]: typeof dimsContent, node: HTMLElement) => {
            if (node) {
                observer(node, getDimsDependencies());
            } else {
                disconnect();
            }
        },
        [getDimsDependencies],
    );
    const refHeaderDims = useCallback((node: HTMLElement) => updateRefDims(dimsHeader, node), [updateRefDims]);
    const refFooterDims = useCallback((node: HTMLElement) => updateRefDims(dimsFooter, node), [updateRefDims]);
    const refRightSidebar = useCallback((node: HTMLElement) => updateRefDims(dimsRightSidebar, node), [updateRefDims]);

    useEffect(() => {
        const animationContainer = getDimsDependencies();
        const disposeFns = [
            dimsContent[0](ref.current),
            dimsOverlay[0](document.querySelector(`#${pageRequestUuid4}`), animationContainer),
        ];
        return () => disposeFns.forEach((c) => c());
    }, []);

    useEffect(() => {
        // Scroll to top automatically at first visit (e.g. `<dialog` auto focuses the first found element)
        fastdom.mutate(() => yieldMainThread().then(() => (ref.current.scrollTop = 0)));
    }, [individualPrivacyOpen]);

    return (
        <Content ref={ref}>
            <A11ySkipToLink href={`#${firstButton}`} onFocus={() => set({ isScreenReader: true })}>
                {skipToConsentChoices}
            </A11ySkipToLink>
            <YieldBannerHeader ref={refHeaderDims} className={headerClassName} />
            <YieldBannerBody rightSideContainerRef={refRightSidebar} />
            <YieldBannerFooter ref={refFooterDims} />
        </Content>
    );
};

export { BannerContent };
