import { action, computed, flow, observable, runInAction } from "mobx";

import type { CommonContextProps } from "@devowl-wp/react-cookie-banner";
import type { FormSettingsValueProps, FormSettingsValuePropsNavItem } from "@devowl-wp/react-cookie-banner-admin";
import type {
    ParamsRouteKeyValueMapPatch,
    RequestRouteKeyValueMapPatch,
    ResponseRouteKeyValueMapPatch,
} from "@devowl-wp/utils";
import { BaseOptions, locationRestKeyValueMapPatch } from "@devowl-wp/utils";

import { BannerLinkCollection } from "../models/bannerLinkCollection.js";
import { BannerLinkModel } from "../models/bannerLinkModel.js";
import { request } from "../utils/request.js";
import { locationRestCountryBypassDatabasePut } from "../wp-api/countryBypassDatabase.put.js";
import { locationRestMigrationDelete } from "../wp-api/migration.delete.js";
import { locationRestNavMenuAddLinksPost } from "../wp-api/navMenuAddLinks.post.js";
import { locationRestRevisionCurrentGet } from "../wp-api/revisionCurrent.get.js";
import { locationRestRevisionCurrentPut } from "../wp-api/revisionCurrent.put.js";
import { locationRestSettings } from "../wp-api/settings.get.js";
import { locationRestSettingsPatch } from "../wp-api/settings.patch.js";

import type { RootStore } from "./stores.js";
import type { ConfigHintTextIdentifier } from "../hooks/useConfigHintText.js";
import type { OtherOptions } from "../types/otherOptions.js";
import type {
    ParamsRouteCountryBypassDatabasePut,
    RequestRouteCountryBypassDatabasePut,
    ResponseRouteCountryBypassDatabasePut,
} from "../wp-api/countryBypassDatabase.put.js";
import type {
    ParamsRouteMigrationDelete,
    RequestRouteMigrationDelete,
    ResponseRouteMigrationDelete,
} from "../wp-api/migration.delete.js";
import type {
    ParamsRouteNavMenuAddLinksPost,
    RequestRouteNavMenuAddLinksPost,
    ResponseRouteNavMenuAddLinksPost,
} from "../wp-api/navMenuAddLinks.post.js";
import type {
    ParamsRouteRevisionCurrentGet,
    RequestRouteRevisionCurrentGet,
    ResponseRouteRevisionCurrentGet,
} from "../wp-api/revisionCurrent.get.js";
import type {
    ParamsRouteRevisionCurrentPut,
    RequestRouteRevisionCurrentPut,
    ResponseRouteRevisionCurrentPut,
} from "../wp-api/revisionCurrent.put.js";
import type { ParamsRouteSettings, RequestRouteSettings, ResponseRouteSettings } from "../wp-api/settings.get.js";
import type {
    ParamsRouteSettingsPatch,
    RequestRouteSettingsPatch,
    ResponseRouteSettingsPatch,
} from "../wp-api/settings.patch.js";

class OptionStore extends BaseOptions {
    @observable
    public busySettings = false;

    @observable
    public busyCountryBypassUpdate = false;

    @observable
    public busyAddLinksToNavigationMenu = false;

    @observable
    public needsRevisionRetrigger = false;

    @observable
    public fetchedBannerLinks = false;

    @observable
    public bannerLinks: BannerLinkCollection;

    @observable
    public publicCookieCount: ResponseRouteRevisionCurrentGet["public_cookie_count"] = 0;

    @observable
    public allCookieCount: ResponseRouteRevisionCurrentGet["all_cookie_count"] = 0;

    @observable
    public allBlockerCount: ResponseRouteRevisionCurrentGet["all_blocker_count"] = 0;

    @observable
    public allTcfVendorConfigurationCount: ResponseRouteRevisionCurrentGet["all_tcf_vendor_configuration_count"] = 0;

    @observable
    public allScannerResultTemplatesCount: ResponseRouteRevisionCurrentGet["all_scanner_result_templates_count"] = 0;

    @observable
    public allScannerResultExternalUrlsCount: ResponseRouteRevisionCurrentGet["all_scanner_result_external_urls_count"] =
        0;

    @observable
    public cookieCounts: ResponseRouteRevisionCurrentGet["cookie_counts"] = {
        draft: 0,
        private: 0,
        publish: 0,
    };

    @observable
    public cloudReleaseInfo: ResponseRouteRevisionCurrentGet["cloud_release_info"] = {
        blocker: null,
        service: null,
    };

    @observable
    public navMenus: ResponseRouteRevisionCurrentGet["nav_menus"] = [];

    @observable
    public tcfVendorConfigurationCounts?: OptionStore["cookieCounts"];

    @observable
    public templateNeedsUpdate: ResponseRouteRevisionCurrentGet["template_needs_update"] = [];

    @observable
    public checkSavingConsentViaRestApiEndpointWorkingHtml: ResponseRouteRevisionCurrentGet["check_saving_consent_via_rest_api_endpoint_working_html"];

    @observable
    public templateUpdateNoticeHtml: ResponseRouteRevisionCurrentGet["template_update_notice_html"];

    @observable
    public templateSuccessorsNoticeHtml: ResponseRouteRevisionCurrentGet["template_successors_notice_html"];

    @observable
    public googleConsentModeNoticesHtml: ResponseRouteRevisionCurrentGet["google_consent_mode_notices_html"] = [];

    @observable
    public servicesDataProcessingInUnsafeCountriesNoticeHtml: ResponseRouteRevisionCurrentGet["services_data_processing_in_unsafe_countries_notice_html"] =
        "";

    @observable
    public servicesWithEmptyPrivacyPolicyNoticeHtml: ResponseRouteRevisionCurrentGet["services_with_empty_privacy_policy_notice_html"] =
        "";

    @observable
    public createdTagManagers: ResponseRouteRevisionCurrentGet["created_tag_managers"] = {
        gtm: [],
        mtm: [],
    };

    @observable
    public contexts: ResponseRouteRevisionCurrentGet["contexts"] = { "": "" };

    @observable
    public dashboardMigration: ResponseRouteRevisionCurrentGet["dashboard_migration"];

    @observable
    public fomoCoupon: ResponseRouteRevisionCurrentGet["fomo_coupon"];

    @observable
    public isBannerActive: ResponseRouteSettings["rcb-banner-active"] = false;

    @observable
    public isBlockerActive: ResponseRouteSettings["rcb-blocker-active"] = false;

    @observable
    public hidePageIds: FormSettingsValueProps["hidePageIds"] = [];

    @observable
    public setCookiesViaManager: ResponseRouteSettings["rcb-set-cookies-via-manager"];

    @observable
    public operatorCountry: ResponseRouteSettings["rcb-operator-country"];

    @observable
    public operatorContactAddress: ResponseRouteSettings["rcb-operator-contact-address"];

    @observable
    public operatorContactPhone: ResponseRouteSettings["rcb-operator-contact-phone"];

    @observable
    public operatorContactEmail: ResponseRouteSettings["rcb-operator-contact-email"];

    @observable
    public operatorContactFormId: ResponseRouteSettings["rcb-operator-contact-form-id"];

    @observable
    public cookiePolicyId: ResponseRouteSettings["rcb-cookie-policy-id"];

    @observable
    public territorialLegalBasis: CommonContextProps["territorialLegalBasis"];

    @observable
    public isAcceptAllForBots: ResponseRouteSettings["rcb-accept-all-for-bots"];

    @observable
    public isRespectDoNotTrack: ResponseRouteSettings["rcb-respect-do-not-track"];

    @observable
    public isBannerLessConsent: ResponseRouteSettings["rcb-banner-less-consent"];

    @observable
    public bannerLessConsentShowOnPageIds: FormSettingsValueProps["bannerLessConsentShowOnPageIds"];

    @observable
    public cookieDuration: ResponseRouteSettings["rcb-cookie-duration"];

    @observable
    public failedConsentDocumentationHandling: ResponseRouteSettings["rcb-failed-consent-documentation-handling"];

    @observable
    public isSaveIp: ResponseRouteSettings["rcb-save-ip"];

    @observable
    public isDataProcessingInUnsafeCountries: ResponseRouteSettings["rcb-data-processing-in-unsafe-countries"];

    @observable
    public isAgeNotice: ResponseRouteSettings["rcb-age-notice"];

    @observable
    public ageNoticeAgeLimit: ResponseRouteSettings["rcb-age-notice-age-limit"];

    @observable
    public isListServicesNotice: ResponseRouteSettings["rcb-list-services-notice"];

    @observable
    public isConsentForwarding: ResponseRouteSettings["rcb-consent-forwarding"];

    @observable
    public forwardTo: FormSettingsValueProps["forwardTo"] = [];

    @observable
    public crossDomains: ResponseRouteSettings["rcb-cross-domains"];

    // Affiliate settings are only available and registered in PRO version
    @observable
    public affiliateLink?: ResponseRouteSettings["rcb-affiliate-link"];

    @observable
    public affiliateLabelBehind?: ResponseRouteSettings["rcb-affiliate-label-behind"];

    @observable
    public affiliateLabelDescription?: ResponseRouteSettings["rcb-affiliate-description"];

    // Country Bypass settings (all optional for free version)
    @observable
    public isCountryBypass?: ResponseRouteSettings["rcb-country-bypass"];

    @observable
    public countryBypassCountries: FormSettingsValueProps["countryBypassCountries"] = [];

    @observable
    public countryBypassType?: ResponseRouteSettings["rcb-country-bypass-type"];

    @observable
    public countryBypassDbDownloadTime?: ResponseRouteSettings["rcb-country-bypass-db-download-time"];

    // TCF compatibility settings (all optional for free version)
    @observable
    public isTcf: ResponseRouteSettings["rcb-tcf"] = false;

    @observable
    public tcfAcceptedTime?: ResponseRouteSettings["rcb-tcf-accepted-time"];

    @observable
    public tcfGvlDownloadTime?: ResponseRouteSettings["rcb-tcf-gvl-download-time"];

    @observable
    public isGcm?: ResponseRouteSettings["rcb-gcm"] = false;

    @observable
    public isGcmShowRecommandationsWithoutConsent?: ResponseRouteSettings["rcb-gcm-recommandations"] = false;

    @observable
    public isGcmCollectAdditionalDataViaUrlParameters?: ResponseRouteSettings["rcb-gcm-additional-url-parameters"] =
        false;

    @observable
    public isGcmRedactAdsDataWithoutConsent?: ResponseRouteSettings["rcb-gcm-redact-without-consent"] = true;

    @observable
    public isGcmListPurposes?: ResponseRouteSettings["rcb-gcm-list-purposes"] = true;

    @observable
    public consentDuration: ResponseRouteSettings["rcb-consent-duration"];

    @observable
    public consentsDeletedAt: ResponseRouteRevisionCurrentGet["consents_deleted_at"];

    @observable
    public bannerlessConsentChecks: ResponseRouteRevisionCurrentGet["bannerless_consent_checks"] = {
        essential: [],
        legalBasisConsentWithoutVisualContentBlocker: [],
        legalBasisLegitimateInterest: [],
    };

    @observable
    public isBannerStickyLinksEnabled?: ResponseRouteSettings["rcb-banner-sticky-links-enabled"] = false;

    // Implement "others" property in your Assets.php;
    @observable
    public others: OtherOptions;

    /**
     * Ignore real-cookie-banner cookie as it is hidden when no other cookie is created.
     */
    @computed
    public get isOnlyRcbCookieCreated() {
        return this.allCookieCount === 1 && (!this.isTcf || !this.allTcfVendorConfigurationCount);
    }

    @computed
    public get areSettingsFetched() {
        return this.isRespectDoNotTrack !== undefined;
    }

    public readonly pureSlug: ReturnType<typeof BaseOptions.getPureSlug>;

    public readonly pureSlugCamelCased: ReturnType<typeof BaseOptions.getPureSlug>;

    public readonly rootStore: RootStore;

    public constructor(rootStore: RootStore) {
        super();
        this.rootStore = rootStore;
        this.pureSlug = BaseOptions.getPureSlug(process.env.slug);
        this.pureSlugCamelCased = BaseOptions.getPureSlug(process.env.slug, true);

        // Use the localized WP object to fill this object values.
        runInAction(() => {
            Object.assign(this, (window as any)[this.pureSlugCamelCased]);
            this.bannerLinks = new BannerLinkCollection(this);
            this.fomoCoupon = this.others.fomoCoupon;
        });
    }

    public fetchSettings: (setFrom?: ResponseRouteSettings) => Promise<void> = flow(function* (
        this: OptionStore,
        setFrom,
    ) {
        this.busySettings = true;
        try {
            const result: ResponseRouteSettings =
                setFrom ||
                (yield request<RequestRouteSettings, ParamsRouteSettings, ResponseRouteSettings>({
                    location: locationRestSettings,
                }));

            this.isBannerActive = result["rcb-banner-active"];
            this.isBlockerActive = result["rcb-blocker-active"];
            this.hidePageIds = (result["rcb-hide-page-ids"] || "").split(",").map(Number).filter(Boolean);
            this.setCookiesViaManager = result["rcb-set-cookies-via-manager"] || "none";
            this.operatorCountry = result["rcb-operator-country"];
            this.operatorContactAddress = result["rcb-operator-contact-address"];
            this.operatorContactPhone = result["rcb-operator-contact-phone"];
            this.operatorContactEmail = result["rcb-operator-contact-email"];
            this.operatorContactFormId = result["rcb-operator-contact-form-id"];
            this.cookiePolicyId = result["rcb-cookie-policy-id"];
            this.territorialLegalBasis = result["rcb-territorial-legal-basis"].split(
                ",",
            ) as OptionStore["territorialLegalBasis"];
            this.isAcceptAllForBots = result["rcb-accept-all-for-bots"];
            this.isRespectDoNotTrack = result["rcb-respect-do-not-track"];
            this.isBannerLessConsent = result["rcb-banner-less-consent"];
            this.bannerLessConsentShowOnPageIds = (result["rcb-banner-less-show-on-page-ids"] || "")
                .split(",")
                .map(Number)
                .filter(Boolean);
            this.cookieDuration = result["rcb-cookie-duration"];
            this.failedConsentDocumentationHandling = result["rcb-failed-consent-documentation-handling"];
            this.isSaveIp = result["rcb-save-ip"];
            this.isDataProcessingInUnsafeCountries = result["rcb-data-processing-in-unsafe-countries"];
            this.isAgeNotice = result["rcb-age-notice"];
            this.ageNoticeAgeLimit = result["rcb-age-notice-age-limit"];
            this.isListServicesNotice = result["rcb-list-services-notice"];
            this.isConsentForwarding = result["rcb-consent-forwarding"] || false;
            this.forwardTo = (result["rcb-forward-to"] || "").split("|").filter(Boolean);
            this.crossDomains = result["rcb-cross-domains"] || "";
            this.isCountryBypass = result["rcb-country-bypass"];
            this.countryBypassCountries = (result["rcb-country-bypass-countries"] || "").split(",").filter(Boolean);
            this.countryBypassType = result["rcb-country-bypass-type"];
            this.countryBypassDbDownloadTime = result["rcb-country-bypass-db-download-time"];
            this.isTcf = result["rcb-tcf"];
            this.tcfAcceptedTime = result["rcb-tcf-accepted-time"];
            this.tcfGvlDownloadTime = result["rcb-tcf-gvl-download-time"];
            this.consentDuration = result["rcb-consent-duration"];

            if (process.env.PLUGIN_CTX === "pro") {
                /* onlypro: start */
                this.isGcm = result["rcb-gcm"];
                this.isGcmShowRecommandationsWithoutConsent = result["rcb-gcm-recommandations"];
                this.isGcmCollectAdditionalDataViaUrlParameters = result["rcb-gcm-additional-url-parameters"];
                this.isGcmRedactAdsDataWithoutConsent = result["rcb-gcm-redact-without-consent"];
                this.isGcmListPurposes = result["rcb-gcm-list-purposes"];

                this.affiliateLink = result["rcb-affiliate-link"];
                this.affiliateLabelBehind = result["rcb-affiliate-label-behind"];
                this.affiliateLabelDescription = result["rcb-affiliate-description"];

                this.isBannerStickyLinksEnabled = result["rcb-banner-sticky-links-enabled"];
                /* onlypro: end */
            }

            yield this.fetchCurrentRevision();
        } catch (e) {
            console.log(e);
            throw e;
        } finally {
            this.busySettings = false;
        }
    });

    public fetchBannerLinks: () => Promise<void> = flow(function* (this: OptionStore) {
        yield this.bannerLinks.get({
            request: {
                status: ["draft", "publish", "private"],
            },
            params: {
                per_page: 100, // Fetch all
                context: "edit",
            },
        });

        this.fetchedBannerLinks = true;
    });

    public updateSettings: (
        update: Partial<OptionStore>,
        bannerLinks?: FormSettingsValuePropsNavItem[],
    ) => Promise<void> = flow(function* (
        this: OptionStore,
        {
            isBannerActive,
            isBlockerActive,
            hidePageIds,
            setCookiesViaManager,
            operatorCountry,
            operatorContactAddress,
            operatorContactEmail,
            operatorContactFormId,
            operatorContactPhone,
            cookiePolicyId,
            territorialLegalBasis,
            isAcceptAllForBots,
            isRespectDoNotTrack,
            cookieDuration,
            failedConsentDocumentationHandling,
            isSaveIp,
            isDataProcessingInUnsafeCountries,
            isAgeNotice,
            isBannerLessConsent,
            bannerLessConsentShowOnPageIds,
            ageNoticeAgeLimit,
            isListServicesNotice,
            isConsentForwarding,
            forwardTo,
            crossDomains,
            affiliateLink,
            affiliateLabelBehind,
            affiliateLabelDescription,
            isCountryBypass,
            countryBypassCountries,
            countryBypassType,
            isTcf,
            isGcm,
            isGcmShowRecommandationsWithoutConsent,
            isGcmCollectAdditionalDataViaUrlParameters,
            isGcmRedactAdsDataWithoutConsent,
            isGcmListPurposes,
            consentDuration,
            isBannerStickyLinksEnabled,
        },
        bannerLinks,
    ) {
        this.busySettings = true;
        try {
            const result: ResponseRouteSettingsPatch = yield request<
                RequestRouteSettingsPatch,
                ParamsRouteSettingsPatch,
                ResponseRouteSettingsPatch
            >({
                location: locationRestSettingsPatch,
                request: {
                    ...(isBannerActive === undefined
                        ? {}
                        : {
                              "rcb-banner-active": isBannerActive,
                          }),
                    ...(isBlockerActive === undefined
                        ? {}
                        : {
                              "rcb-blocker-active": isBlockerActive,
                          }),
                    ...(hidePageIds === undefined
                        ? {}
                        : {
                              "rcb-hide-page-ids": hidePageIds.join(","),
                          }),
                    ...(setCookiesViaManager === undefined
                        ? {}
                        : {
                              "rcb-set-cookies-via-manager": setCookiesViaManager,
                          }),
                    ...(operatorCountry === undefined
                        ? {}
                        : {
                              "rcb-operator-country": operatorCountry,
                          }),
                    ...(operatorContactAddress === undefined
                        ? {}
                        : {
                              "rcb-operator-contact-address": operatorContactAddress,
                          }),
                    ...(operatorContactPhone === undefined
                        ? {}
                        : {
                              "rcb-operator-contact-phone": operatorContactPhone,
                          }),
                    ...(operatorContactEmail === undefined
                        ? {}
                        : {
                              "rcb-operator-contact-email": operatorContactEmail,
                          }),
                    ...(operatorContactFormId === undefined
                        ? {}
                        : {
                              "rcb-operator-contact-form-id": operatorContactFormId,
                          }),
                    ...(cookiePolicyId === undefined
                        ? {}
                        : {
                              "rcb-cookie-policy-id": cookiePolicyId,
                          }),
                    ...(territorialLegalBasis === undefined
                        ? {}
                        : {
                              "rcb-territorial-legal-basis": territorialLegalBasis.join(","),
                          }),
                    ...(isAcceptAllForBots === undefined
                        ? {}
                        : {
                              "rcb-accept-all-for-bots": isAcceptAllForBots,
                          }),
                    ...(isBannerLessConsent === undefined
                        ? {}
                        : {
                              "rcb-banner-less-consent": isBannerLessConsent,
                          }),
                    ...(bannerLessConsentShowOnPageIds === undefined
                        ? {}
                        : {
                              "rcb-banner-less-show-on-page-ids": bannerLessConsentShowOnPageIds.join(","),
                          }),
                    ...(isRespectDoNotTrack === undefined
                        ? {}
                        : {
                              "rcb-respect-do-not-track": isRespectDoNotTrack,
                          }),
                    ...(cookieDuration === undefined
                        ? {}
                        : {
                              "rcb-cookie-duration": cookieDuration,
                          }),
                    ...(failedConsentDocumentationHandling === undefined
                        ? {}
                        : {
                              "rcb-failed-consent-documentation-handling": failedConsentDocumentationHandling,
                          }),
                    ...(isSaveIp === undefined
                        ? {}
                        : {
                              "rcb-save-ip": isSaveIp,
                          }),
                    ...(isDataProcessingInUnsafeCountries === undefined
                        ? {}
                        : {
                              "rcb-data-processing-in-unsafe-countries": isDataProcessingInUnsafeCountries,
                          }),
                    ...(isAgeNotice === undefined
                        ? {}
                        : {
                              "rcb-age-notice": isAgeNotice,
                          }),
                    ...(ageNoticeAgeLimit === undefined
                        ? {}
                        : {
                              "rcb-age-notice-age-limit": ageNoticeAgeLimit,
                          }),
                    ...(isListServicesNotice === undefined
                        ? {}
                        : {
                              "rcb-list-services-notice": isListServicesNotice,
                          }),
                    ...(isConsentForwarding === undefined
                        ? {}
                        : {
                              "rcb-consent-forwarding": isConsentForwarding,
                          }),
                    ...(forwardTo === undefined
                        ? {}
                        : {
                              "rcb-forward-to": forwardTo.join("|"),
                          }),
                    ...(crossDomains === undefined
                        ? {}
                        : {
                              "rcb-cross-domains": crossDomains,
                          }),
                    ...(isCountryBypass === undefined
                        ? {}
                        : {
                              "rcb-country-bypass": isCountryBypass,
                          }),
                    ...(countryBypassCountries === undefined
                        ? {}
                        : {
                              "rcb-country-bypass-countries": countryBypassCountries.join(","),
                          }),
                    ...(countryBypassType === undefined
                        ? {}
                        : {
                              "rcb-country-bypass-type": countryBypassType,
                          }),
                    ...(isTcf === undefined
                        ? {}
                        : {
                              "rcb-tcf": isTcf,
                          }),
                    ...(process.env.PLUGIN_CTX === "pro"
                        ? isGcm === undefined
                            ? {}
                            : {
                                  "rcb-gcm": isGcm,
                              }
                        : {}),
                    ...(process.env.PLUGIN_CTX === "pro"
                        ? isGcmShowRecommandationsWithoutConsent === undefined
                            ? {}
                            : {
                                  "rcb-gcm-recommandations": isGcmShowRecommandationsWithoutConsent,
                              }
                        : {}),
                    ...(process.env.PLUGIN_CTX === "pro"
                        ? isGcmCollectAdditionalDataViaUrlParameters === undefined
                            ? {}
                            : {
                                  "rcb-gcm-additional-url-parameters": isGcmCollectAdditionalDataViaUrlParameters,
                              }
                        : {}),
                    ...(process.env.PLUGIN_CTX === "pro"
                        ? isGcmRedactAdsDataWithoutConsent === undefined
                            ? {}
                            : {
                                  "rcb-gcm-redact-without-consent": isGcmRedactAdsDataWithoutConsent,
                              }
                        : {}),
                    ...(process.env.PLUGIN_CTX === "pro"
                        ? isGcmListPurposes === undefined
                            ? {}
                            : {
                                  "rcb-gcm-list-purposes": isGcmListPurposes,
                              }
                        : {}),
                    ...(process.env.PLUGIN_CTX === "pro"
                        ? affiliateLink === undefined
                            ? {}
                            : {
                                  "rcb-affiliate-link": affiliateLink,
                              }
                        : {}),
                    ...(process.env.PLUGIN_CTX === "pro"
                        ? affiliateLabelBehind === undefined
                            ? {}
                            : {
                                  "rcb-affiliate-label-behind": affiliateLabelBehind,
                              }
                        : {}),
                    ...(process.env.PLUGIN_CTX === "pro"
                        ? affiliateLabelDescription === undefined
                            ? {}
                            : {
                                  "rcb-affiliate-description": affiliateLabelDescription,
                              }
                        : {}),
                    ...(consentDuration === undefined
                        ? {}
                        : {
                              "rcb-consent-duration": consentDuration,
                          }),
                    ...(process.env.PLUGIN_CTX === "pro"
                        ? isBannerStickyLinksEnabled === undefined
                            ? {}
                            : {
                                  "rcb-banner-sticky-links-enabled": isBannerStickyLinksEnabled,
                              }
                        : {}),
                },
            });

            if (this.fetchedBannerLinks && bannerLinks) {
                const createdBannerLinks = this.bannerLinks.sortedBannerLinks;

                // Delete banner links
                for (const createdBannerLink of createdBannerLinks) {
                    if (!bannerLinks.find(({ id }) => createdBannerLink.data.id === id)) {
                        yield createdBannerLink.delete();
                    }
                }

                for (let i = 0; i < bannerLinks.length; i++) {
                    const { isExternalUrl, label, pageType, externalUrl, hideCookieBanner, id, pageId, isTargetBlank } =
                        bannerLinks[i];

                    const newMeta = {
                        isExternalUrl,
                        pageType,
                        externalUrl,
                        hideCookieBanner,
                        pageId,
                        isTargetBlank,
                    };
                    if (id) {
                        // Update banner links
                        const existing = createdBannerLinks.find(({ data: { id: existingId } }) => id === existingId);
                        if (existing) {
                            const {
                                data: {
                                    title: { raw: oldLabel },
                                    menu_order: oldMenuOrder,
                                    meta: {
                                        isExternalUrl: oldIsExternalUrl,
                                        pageType: oldPageType,
                                        externalUrl: oldExternalUrl,
                                        hideCookieBanner: oldHideCookieBanner,
                                        pageId: oldPageId,
                                    },
                                },
                            } = existing;

                            if (
                                oldLabel !== label ||
                                oldMenuOrder !== i ||
                                oldIsExternalUrl !== isExternalUrl ||
                                oldPageType !== pageType ||
                                oldPageId !== pageId ||
                                oldExternalUrl !== externalUrl ||
                                oldHideCookieBanner !== hideCookieBanner
                            ) {
                                existing.setLabel(label);
                                existing.setOrder(i);
                                existing.setMeta(newMeta);
                                yield existing.patch();
                            }
                        }
                    } else {
                        // Add new banner links
                        const draft = new BannerLinkModel(this.bannerLinks, {
                            title: {
                                raw: label,
                            },
                            content: {
                                raw: "",
                                protected: false,
                            },
                            status: "publish",
                            menu_order: i,
                            meta: newMeta,
                        });
                        yield draft.persist();
                    }
                }
            }

            this.fetchSettings(result);
            this.rootStore.checklistStore.fetchChecklist();
        } catch (e) {
            console.log(e);
            throw e;
        } finally {
            this.busySettings = false;
        }
    });

    public fetchCurrentRevision: () => Promise<void> = flow(function* (this: OptionStore) {
        this.busySettings = true;
        try {
            this.setFromCurrentRevision(
                yield request<
                    RequestRouteRevisionCurrentGet,
                    ParamsRouteRevisionCurrentGet,
                    ResponseRouteRevisionCurrentGet
                >({
                    location: locationRestRevisionCurrentGet,
                }),
            );
        } catch (e) {
            console.log(e);
            throw e;
        } finally {
            this.busySettings = false;
        }
    });

    public updateCurrentRevision: (data: RequestRouteRevisionCurrentPut) => Promise<void> = flow(function* (
        this: OptionStore,
        data,
    ) {
        this.busySettings = true;
        try {
            this.setFromCurrentRevision(
                yield request<
                    RequestRouteRevisionCurrentPut,
                    ParamsRouteRevisionCurrentPut,
                    ResponseRouteRevisionCurrentPut
                >({
                    location: locationRestRevisionCurrentPut,
                    request: data,
                }),
            );
        } catch (e) {
            console.log(e);
            throw e;
        } finally {
            this.busySettings = false;
        }
    });

    public setModalHintSeen: (identifier: ConfigHintTextIdentifier) => Promise<void> = flow(function* (
        this: OptionStore,
        identifier,
    ) {
        this.busySettings = true;
        try {
            this.others.modalHints.push(identifier); // Immediate push as this can never fail
            yield request<RequestRouteKeyValueMapPatch, ParamsRouteKeyValueMapPatch, ResponseRouteKeyValueMapPatch>({
                location: locationRestKeyValueMapPatch,
                params: {
                    name: "rcb-notice-states",
                    key: `modal-hint-${identifier}`,
                },
                request: {
                    value: true,
                },
            });
        } catch (e) {
            console.log(e);
            throw e;
        } finally {
            this.busySettings = false;
        }
    });

    public dismissConfigProNotice: () => Promise<void> = flow(function* (this: OptionStore) {
        try {
            // Immediate set because it can not fail
            this.others.isConfigProNoticeVisible = false;
            yield request<RequestRouteKeyValueMapPatch, ParamsRouteKeyValueMapPatch, ResponseRouteKeyValueMapPatch>({
                location: locationRestKeyValueMapPatch,
                params: {
                    name: "rcb-notice-states",
                    key: "get-pro-main-button",
                },
                request: {
                    value: true,
                },
            });
        } catch (e) {
            console.log(e);
            throw e;
        }
    });

    public dismissServiceDataProcessingInUnsafeCountriesNotice: () => Promise<void> = flow(function* (
        this: OptionStore,
    ) {
        try {
            // Immediate set because it can not fail
            this.servicesDataProcessingInUnsafeCountriesNoticeHtml = "";
            yield request<RequestRouteKeyValueMapPatch, ParamsRouteKeyValueMapPatch, ResponseRouteKeyValueMapPatch>({
                location: locationRestKeyValueMapPatch,
                params: {
                    name: "rcb-notice-states",
                    key: "service-data-processing-in-unsafe-countries",
                },
                request: {
                    value: false,
                },
            });
        } catch (e) {
            console.log(e);
            throw e;
        }
    });

    public dismissBannerlessConsentLegitimateServicesNotice: () => Promise<void> = flow(function* (this: OptionStore) {
        try {
            // Immediate set because it can not fail
            yield request<RequestRouteKeyValueMapPatch, ParamsRouteKeyValueMapPatch, ResponseRouteKeyValueMapPatch>({
                location: locationRestKeyValueMapPatch,
                params: {
                    name: "rcb-notice-states",
                    key: "dismissed-bannerless-consent-legint-services",
                },
                request: {
                    value: false,
                },
            });
            yield this.fetchCurrentRevision();
        } catch (e) {
            console.log(e);
            throw e;
        }
    });

    public dismissBannerlessConsentServicesWithoutVisualContentBlockerNotice: () => Promise<void> = flow(function* (
        this: OptionStore,
    ) {
        try {
            // Immediate set because it can not fail
            yield request<RequestRouteKeyValueMapPatch, ParamsRouteKeyValueMapPatch, ResponseRouteKeyValueMapPatch>({
                location: locationRestKeyValueMapPatch,
                params: {
                    name: "rcb-notice-states",
                    key: "dismissed-bannerless-consent-services-without-visual-content-blocker",
                },
                request: {
                    value: false,
                },
            });
            yield this.fetchCurrentRevision();
        } catch (e) {
            console.log(e);
            throw e;
        }
    });

    public dismissMigration: () => Promise<void> = flow(function* (this: OptionStore) {
        try {
            // Immediate set because it can not fail
            const { id: migration } = this.dashboardMigration;
            this.dashboardMigration = undefined;
            yield request<RequestRouteMigrationDelete, ParamsRouteMigrationDelete, ResponseRouteMigrationDelete>({
                location: locationRestMigrationDelete,
                params: {
                    migration,
                },
            });
        } catch (e) {
            console.log(e);
            throw e;
        }
    });

    public addLinksToNavigationMenu: (id: string) => Promise<boolean> = flow(function* (this: OptionStore, id) {
        this.busyAddLinksToNavigationMenu = true;
        try {
            const { success }: ResponseRouteNavMenuAddLinksPost = yield request<
                RequestRouteNavMenuAddLinksPost,
                ParamsRouteNavMenuAddLinksPost,
                ResponseRouteNavMenuAddLinksPost
            >({
                location: locationRestNavMenuAddLinksPost,
                request: {
                    id,
                },
            });

            if (success) {
                this.rootStore.checklistStore.fetchChecklist();
                yield this.fetchCurrentRevision();
            }

            return success;
        } catch (e) {
            console.log(e);
            throw e;
        } finally {
            this.busyAddLinksToNavigationMenu = false;
        }
    });

    public updateCountryBypassDatabase: () => Promise<void> = flow(function* (this: OptionStore) {
        this.busyCountryBypassUpdate = true;
        try {
            const { dbDownloadTime }: ResponseRouteCountryBypassDatabasePut = yield request<
                RequestRouteCountryBypassDatabasePut,
                ParamsRouteCountryBypassDatabasePut,
                ResponseRouteCountryBypassDatabasePut
            >({
                location: locationRestCountryBypassDatabasePut,
            });

            this.countryBypassDbDownloadTime = dbDownloadTime;
        } catch (e) {
            console.log(e);
            throw e;
        } finally {
            this.busyCountryBypassUpdate = false;
        }
    });

    @action
    public setFromCurrentRevision({
        contexts,
        created_tag_managers,
        needs_retrigger,
        public_cookie_count,
        all_cookie_count,
        all_blocker_count,
        all_tcf_vendor_configuration_count,
        all_scanner_result_templates_count,
        all_scanner_result_external_urls_count,
        cookie_counts,
        cloud_release_info,
        consents_deleted_at,
        bannerless_consent_checks,
        nav_menus,
        tcf_vendor_configuration_counts,
        dashboard_migration,
        fomo_coupon,
        template_needs_update,
        check_saving_consent_via_rest_api_endpoint_working_html,
        template_update_notice_html,
        template_successors_notice_html,
        google_consent_mode_notices_html,
        services_data_processing_in_unsafe_countries_notice_html,
        services_with_empty_privacy_policy_notice_html,
    }: ResponseRouteRevisionCurrentGet) {
        this.createdTagManagers = created_tag_managers;
        this.needsRevisionRetrigger = needs_retrigger;
        this.publicCookieCount = public_cookie_count;
        this.allCookieCount = all_cookie_count;
        this.allBlockerCount = all_blocker_count;
        this.allTcfVendorConfigurationCount = all_tcf_vendor_configuration_count;
        this.allScannerResultTemplatesCount = all_scanner_result_templates_count;
        this.allScannerResultExternalUrlsCount = all_scanner_result_external_urls_count;
        this.templateNeedsUpdate = template_needs_update;
        this.templateUpdateNoticeHtml = template_update_notice_html;
        this.checkSavingConsentViaRestApiEndpointWorkingHtml = check_saving_consent_via_rest_api_endpoint_working_html;
        this.templateSuccessorsNoticeHtml = template_successors_notice_html;
        this.googleConsentModeNoticesHtml = google_consent_mode_notices_html;
        this.servicesDataProcessingInUnsafeCountriesNoticeHtml =
            services_data_processing_in_unsafe_countries_notice_html;
        this.servicesWithEmptyPrivacyPolicyNoticeHtml = services_with_empty_privacy_policy_notice_html;
        this.cookieCounts = cookie_counts;
        this.cloudReleaseInfo = cloud_release_info;
        this.consentsDeletedAt = consents_deleted_at;
        this.bannerlessConsentChecks = bannerless_consent_checks;
        this.navMenus = nav_menus;
        this.tcfVendorConfigurationCounts = tcf_vendor_configuration_counts;
        this.contexts = contexts;
        this.dashboardMigration = dashboard_migration;
        this.fomoCoupon = fomo_coupon;
    }

    @action
    public setShowLicenseFormImmediate(state: boolean, isLicensed: boolean) {
        this.others.showLicenseFormImmediate = state;
        this.others.isLicensed = isLicensed;
    }
}

export { OptionStore };
