import Cookie from "js-cookie";

import type { CookieConsentManager } from "../apply/manager.js";

/**
 * See `CookieConsentManager#persistConsent`.
 */
function retryPersistFromQueue(manager: CookieConsentManager, tryImmediate = false) {
    const { decisionCookieName, tcfCookieName, gcmCookieName } = manager.getOptions();
    const removeLocalStorageItems = () => {
        localStorage.removeItem(decisionCookieName);
        localStorage.removeItem(tcfCookieName);
        localStorage.removeItem(gcmCookieName);
        localStorage.removeItem(manager.getConsentQueueName());
    };

    // Make "Show cookie banner again" work
    const showCookieBannerAgainButton = document.querySelector(
        `a[href*="rcb-clear-current-cookie=1"]`,
    ) as HTMLAnchorElement;
    showCookieBannerAgainButton?.addEventListener("click", removeLocalStorageItems);

    if (manager.isConsentQueueLocked()) {
        // Another tab is currently working on the queue, so we wait until the tab gets closed
        const listener = (e: StorageEvent) => {
            if (e.key === manager.getConsentQueueName(true) && !e.newValue) {
                retryPersistFromQueue(manager);
            }
        };
        window.addEventListener("storage", listener);

        return () => {
            window.removeEventListener("storage", listener);
            showCookieBannerAgainButton?.removeEventListener("click", removeLocalStorageItems);
        };
    } else {
        let failedRetries = 0;
        let timeout: ReturnType<typeof setTimeout>;
        const doIt = async () => {
            // Lock for the current tab so no other tab can work on the queue
            manager.isConsentQueueLocked(true);

            const queue = manager.getConsentQueue();
            let timeoutMs = 15000;

            if (queue.length > 0) {
                failedRetries++;
                try {
                    const transaction = queue.shift();
                    const setCookies = queue.length === 0 || !Cookie.get(decisionCookieName);
                    const uuid = await manager.getOption("persistConsent")(transaction, setCookies);

                    // Persist the UUID as previous UUID so it can be shown in the history correctly
                    // See https://regex101.com/r/GY22pw/1
                    const decisionCookieValue = Cookie.get(decisionCookieName);
                    if (decisionCookieValue && decisionCookieValue.indexOf(uuid) === -1) {
                        Cookie.set(decisionCookieName, decisionCookieValue.replace(/^(.*?:.*?):/gm, `$1,${uuid}:`));
                    }

                    manager.setConsentQueue(queue);

                    if (queue.length === 0) {
                        removeLocalStorageItems();
                    }

                    failedRetries = 0;
                    timeoutMs = 1500;
                } catch (e) {
                    // Silence is golden, next try.
                    timeoutMs = failedRetries * 15 * 1000;
                }
            }

            timeout = setTimeout(doIt, timeoutMs);
        };

        // Lock for the current tab so no other tab can work on the queue
        manager.isConsentQueueLocked(true);

        timeout = setTimeout(doIt, tryImmediate ? 0 : 15 * 1000);

        return () => {
            manager.isConsentQueueLocked(false);
            clearTimeout(timeout);
            showCookieBannerAgainButton?.removeEventListener("click", removeLocalStorageItems);
        };
    }
}

export { retryPersistFromQueue };
