import { useEffect } from "react";

import { parents } from "@devowl-wp/react-utils";
import { matchingSelector } from "@devowl-wp/resolve-none-computed-style";

import { useBanner } from "../../contexts/banner.js";

import type { BannerContext } from "../../contexts/banner.js";

const HREF_MATCHER = '[href^="#consent-"]';

/**
 * Listen to anchor links and execute the banner action:
 *
 * ```
 * #consent-change
 * #consent-history
 * #consent-revoke
 * ```
 */
function useBannerActionLinks() {
    const { openBanner, openHistory, revokeConsent } = useBanner();

    useEffect(() => {
        const handleType = (
            type: BannerContext["contextValue"]["activeAction"],
            successMessage: string,
            e: MouseEvent,
        ) => {
            if (!openBanner) {
                // `useBannerActions` is not yet initialized.
                return;
            }

            switch (type) {
                case "change":
                    openBanner(e);
                    break;
                case "history":
                    openHistory(e);
                    break;
                case "revoke":
                    revokeConsent(successMessage, e);
                    break;
                default:
                    break;
            }
        };

        const eventListenerDocumentClick = (e: MouseEvent) => {
            if (!openBanner) {
                // `useBannerActions` is not yet initialized.
                return;
            }

            // Check if one of the parents has a valid hash link
            const element = e.target as HTMLElement;
            (
                parents(element, HREF_MATCHER).concat(
                    matchingSelector(element, HREF_MATCHER) ? [element] : [],
                ) as HTMLLinkElement[]
            ).forEach((parent) => {
                handleType(
                    parent.getAttribute("href").slice(9) as BannerContext["contextValue"]["activeAction"],
                    parent.getAttribute("data-success-message"),
                    e,
                );
            });

            // @deprecated Old behavior with simple links like `#change`
            if (matchingSelector(element, ".rcb-sc-link")) {
                handleType(
                    element.getAttribute("href").slice(1) as BannerContext["contextValue"]["activeAction"],
                    element.getAttribute("data-success-message"),
                    e,
                );
            }
        };

        const eventListenerHashChange = () => {
            const { hash } = window.location;
            if (hash.startsWith("#consent-")) {
                handleType(hash.substring(9) as any, undefined, undefined);
            }
        };

        // Allow initial hash to open the cookie banner
        eventListenerHashChange();

        window.addEventListener("hashchange", eventListenerHashChange);
        document.addEventListener("click", eventListenerDocumentClick as any, true);
        return () => {
            window.removeEventListener("hashchange", eventListenerHashChange);
            document.removeEventListener("click", eventListenerDocumentClick as any, true);
        };
    }, [openBanner, openHistory, revokeConsent]);
}

/**
 * With `useBannerActionLinks` we also listen to `hashchange` and show the cookie banner accordingly,
 * e.g. when a script opens the cookie banner via `window.location.hash = "#consent-change"`.
 * When the user closes the dialog again, the `#consent-change` stays and the cookie banner cannot be
 * opened again.
 */
function resetConsentChangeHash() {
    if (window.location.hash.startsWith("#consent-")) {
        window.location.hash = "";
    }
}

export { useBannerActionLinks, resetConsentChangeHash };
