import Cookie from "js-cookie";

import { EServiceTemplateGoogleConsentModeTypes } from "@devowl-wp/api-real-cookie-banner";

import { getUserGcmDecision } from "./getUserDecision.js";
import { PRESET_ID_TAG_MANAGER_REGEXP } from "../apply/getManagerDependingVariables.js";
import { APPLY_INTERACTIVE_EVENT } from "../events/applyInteractive.js";

import type { CookieConsentManagerOptions } from "../apply/manager.js";
import type { ApplyInteractiveEvent } from "../events/applyInteractive.js";

/**
 * Dispatch events to the `gtag` so the Google Consent Mode can work with the consent status.
 */
function gcmDispatcher({
    gcmCookieName,
    groups,
    setCookiesViaManager,
}: Pick<CookieConsentManagerOptions, "gcmCookieName" | "groups" | "setCookiesViaManager">) {
    document.addEventListener(APPLY_INTERACTIVE_EVENT, (({
        detail: { services: acceptedServices },
    }: CustomEvent<ApplyInteractiveEvent>) => {
        const { gtag } = window;
        const cookieExists = !!Cookie.get(gcmCookieName);

        if (gtag && cookieExists) {
            const consent = getUserGcmDecision(gcmCookieName);
            gtag("consent", "update", {
                // Custom consent types representing our unique name of each service
                ...(setCookiesViaManager === "googleTagManagerWithGcm"
                    ? (groups
                          .map(({ items }) => items)
                          .flat()
                          .reduce(
                              (p, { id, uniqueName }) => {
                                  if (uniqueName && !PRESET_ID_TAG_MANAGER_REGEXP.test(uniqueName)) {
                                      p[uniqueName] = acceptedServices.some(
                                          ({ service: { id: acceptedId } }) => acceptedId === id,
                                      )
                                          ? "granted"
                                          : "denied";
                                  }
                                  return p;
                              },
                              {} as Record<string, Gtag.ConsentParams["ad_storage"]>,
                          ) as any)
                    : []),
                // Predefined consent types
                ...Object.values(EServiceTemplateGoogleConsentModeTypes).reduce(
                    (p, c) => {
                        p[c] = consent.indexOf(c) > -1 ? "granted" : "denied";
                        return p;
                    },
                    {} as Record<EServiceTemplateGoogleConsentModeTypes, Gtag.ConsentParams["ad_storage"]>,
                ),
            });
        }
    }) as any);
}

export { gcmDispatcher };
