import { useEffect, useMemo } from "react";

import { findUsedGcmConsentTypes } from "@devowl-wp/cookie-consent-web-client";
import { HTML_ATTRIBUTE_CONFIRM } from "@devowl-wp/headless-content-unblocker";
import { yieldLazyLoad } from "@devowl-wp/react-utils";

import { BlockerHeroDialog } from "./hero/dialog.js";
import { BlockerHeroContainer } from "./heroContainer.js";
import { BlockerTextContainer } from "./textContainer.js";
import { useBlocker } from "../../contexts/blocker.js";
import { useStylesheetProvider } from "../../contexts/stylesheet.js";
import { useBlockerClassName } from "../../hooks/blocker/useBlockerClassName.js";
import { useBlockerMissingServices } from "../../hooks/blocker/useBlockerMissingServices.js";
import { useA11yId } from "../../hooks/useA11yId.js";
import { useMainStylesheetForContext } from "../../hooks/useMainStylesheetForContext.js";

import type { ComponentProps, FC, HTMLAttributes } from "react";

const YieldBlockerTextContainer = yieldLazyLoad(Promise.resolve(BlockerTextContainer));
const YieldBlockerHeroContainer = yieldLazyLoad(Promise.resolve(BlockerHeroContainer));

const Blocker: FC<{ skipInitialConsent?: boolean }> = ({ skipInitialConsent }) => {
    const stylesheet = useMainStylesheetForContext();
    const { description: id } = stylesheet.reactRootSymbol;

    const {
        recorder,
        isGcm,
        blocker: { visualType, visualThumbnail },
        blockedNode,
        createBefore,
        updateGcmConsentTypeChecked,
    } = useBlocker();

    const confirmOptions = useMemo<Pick<ComponentProps<typeof BlockerHeroDialog>, "fixed"> | null>(
        () => JSON.parse(blockedNode?.getAttribute(HTML_ATTRIBUTE_CONFIRM) || null),
        [blockedNode],
    );

    const [StylesheetProvider, stylesheetContextValue] = useStylesheetProvider(stylesheet);

    const useClassName = useBlockerClassName(stylesheet);
    const a11yExpanded = useA11yId(stylesheet);
    const missingServices = useBlockerMissingServices();

    // Prefill requested consent types
    useEffect(() => {
        if (process.env.PLUGIN_CTX === "pro" && isGcm && !skipInitialConsent) {
            /* onlypro:start */
            findUsedGcmConsentTypes(missingServices).forEach((type) => updateGcmConsentTypeChecked(type, true));
            /* onlypro:end */
        }
    }, [isGcm, skipInitialConsent]);

    // Automatically start recorder if one exists
    useEffect(() => {
        if (recorder) {
            recorder.restart();
            return () => {
                recorder.toggle(false);
            };
        }

        return () => {
            // Silence is golden.
        };
    }, []);

    const attr: HTMLAttributes<HTMLDivElement> = {
        id: a11yExpanded,
    };
    const dialogAttr: Omit<ComponentProps<typeof BlockerHeroDialog>, "heroContainerRef"> = {
        blockerClassName: useClassName,
        blockerOverlayId: `${id}-o`,
    };

    return (
        <StylesheetProvider value={stylesheetContextValue}>
            {confirmOptions ? (
                <BlockerHeroDialog
                    {...dialogAttr}
                    fixed={confirmOptions?.fixed}
                    heroContainerRef={{
                        current:
                            // `createBefore` could be different to `blockedNode` e.g. when using `confirm()` together with `visualParent()`
                            createBefore || blockedNode,
                    }}
                />
            ) : (
                <div className={useClassName} id={id}>
                    {process.env.PLUGIN_CTX === "pro" && visualType === "hero" && visualThumbnail ? (
                        <YieldBlockerHeroContainer {...dialogAttr} {...attr} />
                    ) : (
                        <YieldBlockerTextContainer {...attr} />
                    )}
                </div>
            )}
        </StylesheetProvider>
    );
};

export { Blocker };
