import { useEffect } from "react";

import {
    preDecisionGateway,
    preDecisionGatewayDynamicRequest,
    preDecisionGatewayEventPromises,
    preDecisionGatewayHasPageClass,
    preDecisionGatewayIsCrawler,
    preDecisionGatewayIsDoNotTrack,
    preDecisionGatewayIsPreventPreDecision,
    preDecisionGatewaySupportsCookies,
    preDecisionGatewayUserConsent,
    prepareTcfString,
} from "@devowl-wp/cookie-consent-web-client";
import type { BannerContext } from "@devowl-wp/react-cookie-banner";
import { commonRequest } from "@devowl-wp/utils";

import { getCookieConsentManager } from "../others/getCookieConsentManager.js";
import { getOptionsFromWindow } from "../utils/getOptionsFromWindow.js";
import { isCustomize } from "../utils/isCustomize.js";
import { locationRestConsentDynamicPredecisionGet } from "../wp-api/consentDynamicPredecision.get.js";

import type {
    ParamsRouteConsentDynamicPredecisionGet,
    RequestRouteConsentDynamicPredecisionGet,
    ResponseRouteConsentDynamicPredecisionGet,
} from "../wp-api/consentDynamicPredecision.get.js";

/**
 * Do some decision gateways like DNT, Bot / Crawler and Decision and depending
 * on that, show the Banner initially.
 */
function useBannerPreDecisionGateway(contextValue: BannerContext["contextValue"]) {
    useEffect(() => {
        // Only run this predecision mechanism once and when not in customize
        if (isCustomize()) {
            return;
        }

        const {
            restNamespace,
            restRoot,
            restQuery,
            restNonce,
            restPathObfuscateOffset,
            others: {
                isPreventPreDecision,
                isInvalidateImplicitUserConsent,
                hasDynamicPreDecisions,
                frontend: { isRespectDoNotTrack, isAcceptAllForBots },
            },
        } = getOptionsFromWindow();

        const { onSave, suspense } = contextValue;

        preDecisionGateway<[BannerContext["contextValue"]]>(getCookieConsentManager(), {
            gateways: [
                // The `tcf` object is asynchronous, so we need to wait on it
                async () => {
                    await suspense.tcf;
                    return false;
                },
                preDecisionGatewayEventPromises,
                preDecisionGatewaySupportsCookies,
                preDecisionGatewayUserConsent,
                preDecisionGatewayHasPageClass(["login-action-"], "force-cookie-banner"),
                preDecisionGatewayIsCrawler(isAcceptAllForBots ? "all" : false),
                preDecisionGatewayIsDoNotTrack(isRespectDoNotTrack),
                preDecisionGatewayDynamicRequest(
                    async () => {
                        const { clientWidth, clientHeight } = document.documentElement;

                        let tcfString: () => string;
                        if (process.env.IS_TCF === "1" && suspense.tcf) {
                            tcfString = prepareTcfString((await suspense.tcf).model, "implicit_essential");
                        }

                        return commonRequest<
                            RequestRouteConsentDynamicPredecisionGet,
                            ParamsRouteConsentDynamicPredecisionGet,
                            ResponseRouteConsentDynamicPredecisionGet
                        >({
                            location: locationRestConsentDynamicPredecisionGet,
                            options: {
                                restNamespace,
                                restRoot,
                                restQuery,
                                restNonce,
                                restPathObfuscateOffset,
                            },
                            sendRestNonce: false,
                            sendReferer: true,
                            request: {
                                viewPortWidth: clientWidth,
                                viewPortHeight: clientHeight,
                                referer: window.location.href,
                                tcfStringImplicitEssentials: tcfString ? tcfString() : undefined,
                            },
                        });
                    },
                    10000,
                    hasDynamicPreDecisions,
                ),
                preDecisionGatewayIsPreventPreDecision(isPreventPreDecision),
            ],
            args: [contextValue],
            isInvalidateImplicitUserConsent,
            onIsDoNotTrack: () => {
                onSave(true, "none");
            },
            onShowCookieBanner: () => {
                contextValue.set({
                    visible: true,
                });
            },
        });
    }, []);
}

export { useBannerPreDecisionGateway };
