import { App, Form, Spin, Tabs } from "antd";
import { toJS } from "mobx";
import { observer } from "mobx-react";
import { useCallback, useEffect, useMemo } from "react";
import { useNavigate, useParams } from "react-router-dom";

import { createCopy } from "@devowl-wp/multilingual";
import type { CommonContextProps } from "@devowl-wp/react-cookie-banner";
import type { FormSettingsContext, FormSettingsValueProps } from "@devowl-wp/react-cookie-banner-admin";
import {
    FormSettingsAffiliateTabContent,
    FormSettingsConsentTabContent,
    FormSettingsCountryBypassTabContent,
    FormSettingsFooter,
    FormSettingsGeneralTabContent,
    FormSettingsGoogleConsentModeTabContent,
    FormSettingsMultisiteTabContent,
    FormSettingsResetTabContent,
    FormSettingsTcfTabContent,
    useFormSettingsHandler,
    useFormSettingsProvider,
    useNavLinksPageTypes,
} from "@devowl-wp/react-cookie-banner-admin";
import { RouteHttpVerb } from "@devowl-wp/utils";

import { useLocationQuery } from "../../../hooks/useLocationQuery.js";
import { useRouteTcfVendorConfiguration } from "../../../hooks/useRouteTcfVendorConfiguration.js";
import { useStores } from "../../../store/stores.js";
import { __ } from "../../../utils/i18n.js";
import { request } from "../../../utils/request.js";
import { locationRestCreateCookiePolicyPost } from "../../../wp-api/createCookiePolicy.post.js";
import { locationRestForwardEndpointsGet } from "../../../wp-api/forwardEndpoints.get.js";
import { CSS_SPINNER_IN_CONTENT } from "../../configApp.js";
import { PostTypeSelect } from "../../postTypeSelect.js";
import { ConfigContent } from "../content.js";
import { ConfigHintModal } from "../hintModal.js";

import type { BannerLinkModel } from "../../../models/bannerLinkModel.js";
import type {
    ParamsRouteCreateCookiePolicyPost,
    RequestRouteCreateCookiePolicyPost,
    ResponseRouteCreateCookiePolicyPost,
} from "../../../wp-api/createCookiePolicy.post.js";
import type {
    ParamsRouteForwardEndpointsGet,
    RequestRouteForwardEndpointsGet,
    ResponseRouteForwardEndpointsGet,
} from "../../../wp-api/forwardEndpoints.get.js";
import type { ComponentProps, FC } from "react";

const LAYOUT = {
    labelCol: { span: 6 },
    wrapperCol: { span: 16 },
};

/*const TAIL_LAYOUT: typeof LAYOUT = {
    wrapperCol: { offset: 8, span: 16 }
};*/

const SettingsForm: FC = observer(() => {
    const { message } = App.useApp();
    const tab = useParams().tab || "";
    const navigate = useNavigate();
    const { tcfIntegrationItem, navigateAfterTcfActivation } = useLocationQuery();
    const { link: tcfLink } = useRouteTcfVendorConfiguration();
    const { optionStore, checklistStore, tcfStore } = useStores();
    const availablePageTypesNonMultiple = useNavLinksPageTypes()
        .map(({ multiple, name }) => !multiple && name)
        .filter(Boolean);
    const firstTimeSave = useMemo(
        () => checklistStore.items.filter(({ id }) => id === "save-settings")[0]?.checked === false,
        [checklistStore],
    );
    const {
        fetchedBannerLinks,
        busySettings,
        areSettingsFetched,
        isBannerActive,
        isBlockerActive,
        hidePageIds,
        setCookiesViaManager,
        operatorCountry,
        operatorContactAddress,
        operatorContactEmail,
        operatorContactPhone,
        operatorContactFormId,
        cookiePolicyId,
        territorialLegalBasis,
        isAcceptAllForBots,
        isRespectDoNotTrack,
        isBannerLessConsent,
        bannerLessConsentShowOnPageIds,
        cookieDuration,
        failedConsentDocumentationHandling,
        isSaveIp,
        isDataProcessingInUnsafeCountries,
        isAgeNotice,
        ageNoticeAgeLimit,
        isListServicesNotice,
        isConsentForwarding,
        forwardTo,
        crossDomains,
        affiliateLink,
        affiliateLabelBehind,
        affiliateLabelDescription,
        isCountryBypass,
        countryBypassCountries,
        countryBypassType,
        isTcf,
        tcfAcceptedTime,
        tcfGvlDownloadTime,
        isGcm,
        isGcmShowRecommandationsWithoutConsent,
        isGcmCollectAdditionalDataViaUrlParameters,
        isGcmRedactAdsDataWithoutConsent,
        isGcmListPurposes,
        consentDuration,
        consentsDeletedAt,
        bannerlessConsentChecks,
        countryBypassDbDownloadTime,
        others: {
            customizeValuesBanner: {
                texts: { ageNoticeBanner },
            },
            iso3166OneAlpha2,
            ageNoticeCountryAgeMap,
            predefinedCountryBypassLists,
            frontend: { predefinedDataProcessingInSafeCountriesLists },
            customizeBannerUrl,
            adminUrl,
            resetUrl,
            resetTexts: { dry: resetTextsLanguages, url: resetTextsUrl },
        },
    } = optionStore;

    const { prompt, form, isBusy, defaultValues, onFinish, onFinishFailed, onValuesChange, contextValue } =
        useFormSettingsHandler({
            isCountryBypass,
            isTcf,
            isGcm,
            unloadPromptWhen: ({ nextLocation: { pathname } }) => !pathname.startsWith("/settings"),
            handleSave: async (values) => {
                await optionStore.updateSettings({ ...initialValues, ...values }, values.navLinks);

                // Automatically redirect to next tab after first change of settings
                if (firstTimeSave) {
                    const tabs = ["", "consent", "country-bypass"];
                    const currentIdx = tabs.indexOf(tab);
                    if (currentIdx > -1 && tabs[currentIdx + 1]) {
                        navigate(`/settings/${tabs[currentIdx + 1]}`);
                    }
                }

                // Allow to redirect via URL parameter when activating TCF successfully
                if (navigateAfterTcfActivation && optionStore.tcfGvlDownloadTime) {
                    window.location.href = navigateAfterTcfActivation;
                }
            },
        });

    const handleValuesChange: ComponentProps<typeof Form<typeof initialValues>>["onValuesChange"] = useCallback(
        (changedValues, values) => {
            if (Object.hasOwn(changedValues, "operatorCountry") && values.operatorCountry === "CH") {
                form.setFieldValue("territorialLegalBasis", [
                    "gdpr-eprivacy",
                    "dsg-switzerland",
                ] as CommonContextProps["territorialLegalBasis"]);
            }

            onValuesChange(changedValues, values);
        },
        [onValuesChange],
    );

    useEffect(() => {
        optionStore.fetchBannerLinks();
    }, []);

    const renderPageSelector: FormSettingsContext["initialState"]["renderPageSelector"] = useCallback(
        ({ selectedPageContent, selectedPageUrl, onlyPages, ...rest }) => (
            <PostTypeSelect
                {...rest}
                postType={onlyPages ? ["page"] : undefined}
                forceDefaultLanguage
                applyTitleRenderOnSelectOption
                titleRender={(post, selected) => {
                    const {
                        id,
                        title: { rendered },
                        content: { rendered: contentRendered },
                        link,
                    } = post || {
                        id: 0,
                        title: { rendered: undefined },
                        content: { rendered: "" },
                    };

                    // Missuses `titleRender` to check if the current selected privacy policy has
                    // a sentence about Real Cookie Banner.
                    if (selectedPageContent) {
                        if (selected.indexOf(id) > -1) {
                            selectedPageContent(contentRendered);
                        } else if (selected.length === 0) {
                            selectedPageContent(undefined);
                        }
                    }

                    if (selectedPageUrl) {
                        selectedPageUrl(selected.indexOf(id) > -1 ? link : undefined);
                    }

                    return rendered;
                }}
                perPage={100}
            />
        ),
        [],
    );

    const navLinksFromStoreToFormValue = useCallback(
        (links: BannerLinkModel[]) =>
            links.map(
                (
                    {
                        data: {
                            id,
                            title: { rendered: label },
                            meta: { pageType, isExternalUrl, pageId, externalUrl, hideCookieBanner, isTargetBlank },
                            multilingual,
                        },
                    },
                    i,
                ) => ({
                    id,
                    // Are there duplicate page types which are not allowed to be available multiple times (e.g. privacy policy when deactivating WPML/PolyLang)
                    pageType:
                        availablePageTypesNonMultiple.indexOf(pageType) > -1 &&
                        links.some(
                            (
                                {
                                    data: {
                                        meta: { pageType: thisPageType },
                                    },
                                },
                                thisI,
                            ) => thisI < i && pageType === thisPageType,
                        )
                            ? "other"
                            : pageType,
                    isExternalUrl,
                    pageId,
                    externalUrl,
                    hideCookieBanner,
                    isTargetBlank,
                    label,
                    languages: toJS(multilingual),
                    languageOnClick: async (recordId, { code, id }) => {
                        try {
                            if (id === false) {
                                await createCopy("rcb-banner-links", recordId, code);
                            }

                            // Open the newly created link
                            const url = new URL(window.location.href);
                            url.searchParams.set("lang", code);
                            window.location.href = url.toString();
                        } catch (e) {
                            if (e.responseJSON?.message) {
                                message.error(e.responseJSON.message);
                            } else {
                                throw e;
                            }
                        }
                    },
                }),
            ),
        [],
    );

    const [FormSettingsContextProvider, formSettingsContextValue] = useFormSettingsProvider(
        {
            ...contextValue,
            onPageEditClick: (id) => window.open(`${adminUrl}post.php?post=${id}&action=edit`, "_blank"),
            activeTab: tab,
            resetTextsLanguages,
            onResetTexts: (languages) => {
                window.location.href = `${resetTextsUrl}&${languages.map((lang) => `reset-lang[]=${lang}`).join("&")}`;
            },
            onResetAll: (resetConsents) => {
                window.location.href = `${resetUrl}&${resetConsents ? "&reset-consents" : ""}`;
            },
            onStartTcfVendorConfiguration: () => {
                window.location.href = tcfLink;
            },
            renderPageSelector,
            onHasPrivacyPolicyRCBSentenceChanged: () => {
                checklistStore.probablyFetchByChangedItem("privacy-policy-mention-usage");
            },
            consentsDeletedAt,
            iso3166OneAlpha2,
            ageNotice: ageNoticeBanner,
            ageNoticeCountryAgeMap,
            predefinedCountryBypassLists,
            predefinedDataProcessingInSafeCountriesLists,
            onCustomizeClick: (id) =>
                window.open(
                    `${customizeBannerUrl.replace(
                        /autofocus\[panel]=[\w-]+/,
                        `autofocus[control]=${id}`,
                    )}&return=${encodeURIComponent(window.location.href)}`,
                    "_blank",
                ),
            countryBypassDbDownloadTime,
            tcfAcceptedTime,
            tcfGvlDownloadTime,
            multisiteEndpoints: {
                current: {},
                forwardTo: {},
            },
            bannerlessConsentChecks,
        },
        {
            onCountryBypassUpdateDatabase: () => optionStore.updateCountryBypassDatabase(),
            onTcfUpdateDatabase: () => tcfStore.updateGvl(),
            fetchMultisiteEndpoints: async ({ set }) => {
                const [current, forwardTo] = await Promise.all([
                    request<
                        RequestRouteForwardEndpointsGet,
                        ParamsRouteForwardEndpointsGet,
                        ResponseRouteForwardEndpointsGet
                    >({
                        location: locationRestForwardEndpointsGet,
                        params: {
                            filter: "onlyCurrent",
                        },
                    }),
                    request<
                        RequestRouteForwardEndpointsGet,
                        ParamsRouteForwardEndpointsGet,
                        ResponseRouteForwardEndpointsGet
                    >({
                        location: locationRestForwardEndpointsGet,
                        params: {
                            filter: "notCurrent",
                        },
                    }),
                ]);

                set({ multisiteEndpoints: { current, forwardTo } });
            },
            createCookiePolicy: async () => {
                const { id } = await request<
                    RequestRouteCreateCookiePolicyPost,
                    ParamsRouteCreateCookiePolicyPost,
                    ResponseRouteCreateCookiePolicyPost
                >({
                    location: locationRestCreateCookiePolicyPost,
                });

                return { pageId: id, onNewNavLinks: (navLinks) => optionStore.updateSettings({}, navLinks) };
            },
            deactivateCookiePolicy: async (_, id) => {
                await request({
                    location: {
                        path: `/pages/${id}`,
                        method: RouteHttpVerb.DELETE,
                        namespace: "wp/v2",
                    },
                    request: {
                        force: true,
                    },
                });

                return { onNewNavLinks: (navLinks) => optionStore.updateSettings({}, navLinks) };
            },
        },
        {
            inherit: [
                "isCountryBypass",
                "isGcm",
                "isTcf",
                "tcfGvlDownloadTime",
                "countryBypassDbDownloadTime",
                "activeTab",
            ],
        },
    );

    if (!fetchedBannerLinks || !areSettingsFetched) {
        return <Spin spinning style={CSS_SPINNER_IN_CONTENT} />;
    }

    const initialValues: FormSettingsValueProps = {
        ...defaultValues,
        isBannerActive,
        isBlockerActive,
        hidePageIds: [...hidePageIds],
        setCookiesViaManager,
        operatorCountry,
        operatorContactAddress,
        operatorContactEmail,
        operatorContactPhone,
        operatorContactFormId,
        cookiePolicyId,
        territorialLegalBasis,
        isAcceptAllForBots,
        isRespectDoNotTrack,
        isBannerLessConsent,
        bannerLessConsentShowOnPageIds: [...bannerLessConsentShowOnPageIds],
        cookieDuration,
        failedConsentDocumentationHandling,
        isSaveIp,
        isDataProcessingInUnsafeCountries,
        isAgeNotice,
        ageNoticeAgeLimit,
        isListServicesNotice,
        isGcmShowRecommandationsWithoutConsent,
        isGcmCollectAdditionalDataViaUrlParameters,
        isGcmRedactAdsDataWithoutConsent,
        isGcmListPurposes,
        isConsentForwarding,
        forwardTo: [...forwardTo],
        crossDomains,
        affiliateLink,
        affiliateLabelBehind,
        affiliateLabelDescription,
        countryBypassCountries: [...countryBypassCountries],
        countryBypassType,
        consentDuration,
        navLinks: navLinksFromStoreToFormValue(optionStore.bannerLinks.sortedBannerLinks),
    };

    return (
        <FormSettingsContextProvider value={formSettingsContextValue}>
            <Spin spinning={busySettings || isBusy}>
                {prompt}
                <Form
                    name="settings"
                    initialValues={initialValues}
                    form={form}
                    {...LAYOUT}
                    onFinish={onFinish}
                    onValuesChange={handleValuesChange}
                    onFinishFailed={onFinishFailed}
                    scrollToFirstError={{ behavior: "smooth", block: "center" }}
                    labelWrap
                >
                    <Form.Item noStyle labelCol={{ span: 0 }} wrapperCol={{ span: 24 }}>
                        <Tabs
                            activeKey={tab}
                            onTabClick={(key) => {
                                navigate(`/settings/${key}`);
                            }}
                            items={[
                                {
                                    key: "",
                                    label: __("General"),
                                    children: (
                                        <ConfigContent maxWidth="fixed">
                                            <FormSettingsGeneralTabContent />
                                            <FormSettingsFooter />
                                        </ConfigContent>
                                    ),
                                },
                                {
                                    key: "consent",
                                    label: __("Consent"),
                                    children: (
                                        <ConfigContent maxWidth="fixed">
                                            <FormSettingsConsentTabContent />
                                            <FormSettingsFooter />
                                        </ConfigContent>
                                    ),
                                },
                                {
                                    key: "country-bypass",
                                    label: __("Geo-restriction"),
                                    children: (
                                        <ConfigContent maxWidth="fixed">
                                            <FormSettingsCountryBypassTabContent />
                                            <FormSettingsFooter />
                                        </ConfigContent>
                                    ),
                                },
                                {
                                    key: "tcf",
                                    label: __("Transparency & Consent Framework (TCF)"),
                                    children: (
                                        <ConfigContent maxWidth="fixed">
                                            <FormSettingsTcfTabContent />
                                            <FormSettingsFooter />
                                        </ConfigContent>
                                    ),
                                },
                                {
                                    key: "gcm",
                                    label: __("Google Consent Mode"),
                                    children: (
                                        <ConfigContent maxWidth="fixed">
                                            <FormSettingsGoogleConsentModeTabContent />
                                            <FormSettingsFooter />
                                        </ConfigContent>
                                    ),
                                },
                                {
                                    key: "multisite",
                                    label: __("Consent Forwarding"),
                                    children: (
                                        <ConfigContent maxWidth="fixed">
                                            <FormSettingsMultisiteTabContent />
                                            <FormSettingsFooter />
                                        </ConfigContent>
                                    ),
                                },
                                process.env.PLUGIN_CTX === "pro" &&
                                    tab === "affiliate" && {
                                        key: "affiliate",
                                        label: __("Affiliate"),
                                        children: (
                                            <ConfigContent maxWidth="fixed">
                                                <FormSettingsAffiliateTabContent />
                                                <FormSettingsFooter />
                                            </ConfigContent>
                                        ),
                                    },
                                tab === "reset" && {
                                    key: "reset",
                                    label: __("Reset"),
                                    children: <FormSettingsResetTabContent />,
                                },
                            ].filter(Boolean)}
                        />
                    </Form.Item>
                </Form>
                {tcfIntegrationItem && (
                    <ConfigHintModal
                        always
                        identifier="tcf-integration"
                        title={__("Consent required according to TCF")}
                        sprintfArgs={[tcfIntegrationItem]}
                    />
                )}
            </Spin>
        </FormSettingsContextProvider>
    );
});

export { SettingsForm };
