import { observer } from "mobx-react";
import { useEffect, useMemo, useState } from "react";

import { createTcfModel, getDefaultDecision } from "@devowl-wp/cookie-consent-web-client";
import type { BannerContext } from "@devowl-wp/react-cookie-banner";
import {
    Banner,
    Portal,
    useBannerProvider,
    useBannerStateContextCallbacks,
    useStateContextCallbacks,
} from "@devowl-wp/react-cookie-banner";
import { usePlainCss, waitObject } from "@devowl-wp/react-utils";
import { Player, RECORD_ITEM_TYPE_RESIZE } from "@devowl-wp/web-html-element-interaction-recorder";

import { useStores } from "../../../../store/stores.js";
import { __ } from "../../../../utils/i18n.js";
import { BannerProductionNotice } from "../../../bannerProductionNotice.js";

import type { Consent } from "../../../../models/consent.js";
import type { FC } from "react";

/**
 * Show a banner from a given record in "Consent" table.
 */
const ConsentRecordBanner: FC<{
    record: Consent;
    visible: boolean;
    onClose: BannerContext["modifiers"]["onClose"];
    replayBannerRecord?: boolean;
}> = observer(({ record, visible, onClose, replayBannerRecord }) => {
    /* onlypro:start */
    const { optionStore } = useStores();
    const {
        others: { pageRequestUuid4, bannerI18n, iso3166OneAlpha2 },
    } = optionStore;

    const {
        design_version,
        viewport_width,
        viewport_height,
        button_clicked,
        ui_view,
        tcf_string: tcfString,
        previous_tcf_string: previousTcfString,
        recorder,
        revision: {
            data: {
                groups,
                tcf,
                options,
                websiteOperator,
                predefinedDataProcessingInSafeCountriesLists,
                lazyLoadedDataForSecondView: lazyLoadedDataForSecondViewRevision,
            },
        },
        revision_independent: {
            data: {
                banner: { customizeValuesBanner },
                tcfMetadata,
                links,
                languageSwitcher,
                consentForwardingExternalHosts,
                isPro,
                isLicensed,
                isDevLicense,
                lazyLoadedDataForSecondView: lazyLoadedDataForSecondViewRevisionIndependent,
            },
        },
    } = record;

    const activeAction = visible && ui_view === "change" ? "change" : undefined;
    const [overlayWidth, setOverlayWidth] = useState(viewport_width);
    const [overlayHeight, setOverlayHeight] = useState(viewport_height);

    // TCF compatibility
    const tcfObject = createTcfModel({
        tcf,
        tcfMetadata,
        tcfString:
            activeAction === "change" && replayBannerRecord ? previousTcfString : replayBannerRecord ? "" : tcfString,
    });

    // Modify the width and height of the viewport
    usePlainCss(
        overlayWidth && overlayHeight
            ? `#${pageRequestUuid4} {
    width: ${overlayWidth}px;
    height: ${overlayHeight}px;
    max-width: initial !important;
    top: 50% !important;
    left: 50% !important;
    margin-left: -${overlayWidth / 2}px;
    margin-top: -${overlayHeight / 2}px;
    box-shadow: 0 0 0 3000px rgba(0,0,0,0.95);
}`
            : "",
    );

    useEffect(() => {
        // Replay recorder
        if (replayBannerRecord && recorder) {
            const player = new Player(JSON.parse(recorder));
            const [, dispatch] = player.start({
                // Wait for the overlay as it is parsed through the cookie banner and due to lazy loading components
                // this is not immediately available
                setElement: () => waitObject(() => document.getElementById(pageRequestUuid4)),
                clickWrapper: async (e) => e.querySelector("dialog"),
                afterReplayItem: async (item) => {
                    const [type] = item;
                    if (type === RECORD_ITEM_TYPE_RESIZE) {
                        const [, , width, height] = item;
                        setOverlayWidth(width);
                        setOverlayHeight(height);
                    }
                },
            });
            return dispatch;
        }

        if (record) {
            setOverlayWidth(record.viewport_width);
            setOverlayHeight(record.viewport_height);
        }

        return () => {
            // Silence is golden.
        };
    }, [record, replayBannerRecord]);

    const poweredLink = useMemo(() => {
        const link = document.createElement("a");
        link.target = "_blank";
        link.href = "#";
        link.innerHTML = __("Cookie Consent with Real Cookie Banner");
        return link;
    }, []);

    const { updateGcmConsentTypeChecked } = useStateContextCallbacks<BannerContext>();
    const { updateGroupChecked, updateCookieChecked } = useBannerStateContextCallbacks();

    // Merge lazy loaded data for second view from independent revision
    const lazyLoadedDataForSecondView = useMemo(() => {
        const obj = { ...lazyLoadedDataForSecondViewRevision };
        if (lazyLoadedDataForSecondViewRevisionIndependent.tcf) {
            const revisionVendors = obj.tcf.vendors;
            for (const [vendorId, vendor] of Object.entries(
                lazyLoadedDataForSecondViewRevisionIndependent.tcf.vendors,
            )) {
                if (revisionVendors[vendorId]) {
                    revisionVendors[vendorId] = {
                        ...revisionVendors[vendorId],
                        ...vendor,
                    };
                }
            }
        }
        console.log(obj);
        return obj;
    }, [lazyLoadedDataForSecondViewRevision, lazyLoadedDataForSecondViewRevisionIndependent]);

    const [BannerContextProvider, bannerContextValue] = useBannerProvider(
        {
            ...customizeValuesBanner,
            ...options,

            // In Design Version 8 we have introduced an issue that the frontend banner showed the
            // general description text instead of the text meant for the second view (https://app.clickup.com/t/8694vgm6z)
            ...(design_version === 8 ? { blocker: [] } : {}),

            pageRequestUuid4,
            consentForwardingExternalHosts,
            activeAction,
            iso3166OneAlpha2,
            predefinedDataProcessingInSafeCountriesLists,
            lazyLoadedDataForSecondView,
            poweredLink,
            productionNotice: (
                <BannerProductionNotice
                    isPro={isPro}
                    isLicensed={isLicensed}
                    isDevLicense={isDevLicense}
                    i18n={bannerI18n}
                />
            ),
            tcf: tcfObject,
            tcfFilterBy: "legInt",
            groups,
            languageSwitcher,
            links,
            websiteOperator,
            visible,
            isConsentRecord: true,
            individualPrivacyOpen: ui_view === "change",
            buttonClicked: replayBannerRecord ? undefined : button_clicked,
            designVersion: design_version,
            i18n: bannerI18n,
            consent:
                activeAction === "change" && replayBannerRecord
                    ? record.previous_decision
                    : replayBannerRecord
                      ? getDefaultDecision(groups)
                      : record.decision,
            gcmConsent:
                activeAction === "change" && replayBannerRecord
                    ? record.previous_gcm_consent
                    : replayBannerRecord
                      ? []
                      : record.gcm_consent,
            didGroupFirstChange: false,
            onPersistConsent: async () => {},
            onApplyConsent: async () => {},
        },
        { onClose, updateGroupChecked, updateCookieChecked, updateGcmConsentTypeChecked, onSave: () => {} },
        {
            deps: [record],
        },
    );

    return (
        <Portal className="rcb-customize-banner-container">
            <BannerContextProvider value={bannerContextValue}>
                <Banner />
            </BannerContextProvider>
        </Portal>
    );
    /* onlypro:end */
});

export { ConsentRecordBanner };
