import { Fragment, useEffect, useRef, useState } from "react";

import { EServiceTemplateGoogleConsentModeTypes } from "@devowl-wp/api-real-cookie-banner";
import { createTcfModel, prepareTcfString } from "@devowl-wp/cookie-consent-web-client";
import { extendCommonStylesheet } from "@devowl-wp/web-cookie-banner";

import { useBanner } from "../../../contexts/banner.js";
import { useBannerStylesheet } from "../../../hooks/banner/useBannerStylesheet.js";

import type { BannerContext, BannerHistoryEntry } from "../../../contexts/banner.js";
import type { FC } from "react";

const SELECT_NONE = -1;

const BannerHistorySelect: FC = () => {
    const banner = useBanner();
    const { Select } = useBannerStylesheet().extend(...extendCommonStylesheet);
    const {
        set,
        consent,
        groups,
        tcf,
        isGcm,
        gcmConsent,
        lazyLoadedDataForSecondView,
        activeAction,
        history,
        fetchHistory,
        visible,
        i18n: { historyLabel, historyItemLoadError, historySelectNone },
    } = banner;
    const [selectedEntry, setSelectedEntry] = useState<BannerHistoryEntry>();

    // Save the current consent and group settings to restore
    const [originalContext, setOriginalContext] = useState<BannerHistoryEntry["context"]>({
        consent,
        groups,
        tcf,
        gcmConsent,
        lazyLoadedDataForSecondView,
    });
    const updateOriginalContext = () =>
        setOriginalContext({ consent, groups, tcf, gcmConsent, lazyLoadedDataForSecondView });

    const setInContext = ({ buttonClicked, tcf, gcmConsent, ...rest }: BannerHistoryEntry["context"]) => {
        const additionalChanges: Partial<BannerContext["contextValue"]> = {
            // In case we previously used non-TCF functionality, do not show the TCF banner
            isTcf: !!tcf,
            tcf: null,
            gcmConsent: [],
        };

        if (process.env.IS_TCF === "1" && tcf) {
            Object.assign(additionalChanges, {
                tcf: "gvl" in tcf ? tcf : createTcfModel(tcf),
            });

            if (buttonClicked?.startsWith("implicit_")) {
                prepareTcfString(additionalChanges.tcf.model, buttonClicked);
            }
        }

        /* onlypro:start */
        if (process.env.PLUGIN_CTX === "pro" && isGcm) {
            Object.assign(additionalChanges, {
                gcmConsent: gcmConsent || [],
            });

            if (buttonClicked === "implicit_all") {
                additionalChanges.gcmConsent = Object.values(EServiceTemplateGoogleConsentModeTypes);
            }
        }
        /* onlypro:end */

        set({
            ...rest,
            ...additionalChanges,
        });
    };

    useEffect(() => {
        const defaultContext: BannerHistoryEntry["context"] = {
            consent: [],
            groups: [],
            gcmConsent: [],
            lazyLoadedDataForSecondView: undefined,
        };
        if (selectedEntry) {
            const { context } = selectedEntry;
            if (context) {
                setInContext(context);
            } else {
                setInContext(defaultContext);
            }
        } else {
            setInContext(defaultContext);
        }
    }, [selectedEntry]);

    const fetched = useRef(false);
    useEffect(() => {
        async function fetch() {
            const result = await fetchHistory();
            updateOriginalContext();
            set({ history: result });
            setSelectedEntry(result[0]);
        }

        // We need to wait for the lazy-loaded data so we can safely save the original context
        if (lazyLoadedDataForSecondView && !fetched.current && activeAction === "history" && visible) {
            fetched.current = true;
            fetch();
        }
    }, [lazyLoadedDataForSecondView, activeAction, visible]);

    useEffect(() => {
        if (!visible) {
            fetched.current = false;
        }
    }, [visible]);

    // If we close the history, restore the original state
    useEffect(() => {
        return () => setInContext(originalContext);
    }, []);

    // History can only contain my data, so we can pick the first entry for the history
    const uuid = selectedEntry?.uuid;

    return (
        <Fragment>
            {historyLabel}&nbsp;
            <Select
                disabled={!history?.length}
                value={selectedEntry?.id || SELECT_NONE}
                onChange={(e) => {
                    const value = +e.target.value;
                    for (const entry of history) {
                        const { id } = entry;
                        if (id === value) {
                            setSelectedEntry(entry);
                            break;
                        }
                    }
                }}
            >
                {history?.length > 0 ? (
                    history.map(({ id, isDoNotTrack, isUnblock, isForwarded, created }) => (
                        <option key={id} value={id}>
                            {new Date(created).toLocaleString(document.documentElement.lang)}
                            {isDoNotTrack ? " (Do Not Track)" : ""}
                            {isUnblock ? " (Content Blocker)" : ""}
                            {isForwarded ? " (Consent Forwarding)" : ""}
                        </option>
                    ))
                ) : (
                    <option value={SELECT_NONE}>{historySelectNone}</option>
                )}
            </Select>
            <div style={{ opacity: 0.5, marginTop: 5 }}>UUID: {uuid || "-"}</div>
            {!selectedEntry?.context && <div style={{ fontWeight: "bold", marginTop: 5 }}>{historyItemLoadError}</div>}
        </Fragment>
    );
};

export { BannerHistorySelect };
