import { getDefaultDecision } from "./getDefaultDecision.js";

import type { DecisionConsentGroups, getUserDecision } from "./getUserDecision.js";
import type { CookieConsentManager, CookieConsentManagerTransaction } from "../apply/manager.js";

/**
 * See `CookieConsentManager#persistConsent`.
 */
async function persistWithQueueFallback(transaction: CookieConsentManagerTransaction, manager: CookieConsentManager) {
    // Add the newly added consent to the queue so we can safely retry it again later when it fails
    transaction.createdClientTime = new Date().toISOString();
    const queue = manager.getConsentQueue();
    queue.push(transaction);
    manager.setConsentQueue(queue);

    try {
        await manager.getOption("persistConsent")(transaction, true);

        // Delete again from queue as it got successfully deleted
        manager.setConsentQueue(
            manager
                .getConsentQueue()
                .filter(({ createdClientTime }) => transaction.createdClientTime !== createdClientTime),
        );
    } catch (e) {
        // Save the given consent in localStorage so it can be retrieved through e.g. `getUserDecision` for TCF, GCM, ...
        const {
            groups,
            decisionCookieName,
            tcfCookieName,
            gcmCookieName,
            failedConsentDocumentationHandling,
            revisionHash,
        } = manager.getOptions();
        const isOptimistic = failedConsentDocumentationHandling === "optimistic";
        const { decision, createdClientTime, tcfString, gcmConsent, buttonClicked } = transaction;

        const getUserDecisionValue: ReturnType<typeof getUserDecision> = {
            consent: !isOptimistic
                ? getDefaultDecision(groups, false)
                : decision === "all"
                  ? groups.reduce((p, c) => {
                        p[c.id] = c.items.map(({ id }) => id);
                        return p;
                    }, {} as DecisionConsentGroups)
                  : decision === "essentials"
                    ? getDefaultDecision(groups, false)
                    : decision,
            previousUuids: [],
            revision: revisionHash,
            uuid: createdClientTime,
            created: new Date(createdClientTime),
            buttonClicked,
        };

        localStorage.setItem(decisionCookieName, JSON.stringify(getUserDecisionValue));

        if (tcfString) {
            localStorage.setItem(tcfCookieName, isOptimistic ? tcfString : "");
        }
        if (gcmConsent) {
            localStorage.setItem(gcmCookieName, isOptimistic ? JSON.stringify(gcmConsent) : "[]");
        }
    }
}

export { persistWithQueueFallback };
