import type { EServiceTemplateGoogleConsentModeTypes } from "@devowl-wp/api-real-cookie-banner";
import type {
    ClickableButtonsNamed,
    Tcf,
    TcfDeclarationFilter,
    TcfMetadata,
} from "@devowl-wp/cookie-consent-web-client";
import type {
    FnCreateImmutableContextForSymbol,
    FnCreateImmutableContextProviderForSymbol,
    ImmutableContext,
} from "@devowl-wp/react-utils";
import { useImmutableContext, useImmutableContextProvider } from "@devowl-wp/react-utils";
import type { Customize, MainStylesheetAdditionalCustomizeProperties } from "@devowl-wp/web-cookie-banner";

import type { CommonContextProps } from "../types/commonContext.js";
import type { Declarations, GVL, TCModel } from "@iabtechlabtcf/core";

type LanguageSwitcherEntry = {
    name: string;
    current: boolean;
    flag?: string;
    locale: string;
    url: string;
};

type BannerHistoryEntry = {
    id: number;
    uuid: string;
    isDoNotTrack: boolean;
    isUnblock: boolean;
    isForwarded: boolean;
    created: string;
    context: Pick<
        BannerContext["initialState"],
        "groups" | "consent" | "gcmConsent" | "lazyLoadedDataForSecondView" | "buttonClicked"
    > & {
        // The TCF needs to be converted to a valid TCF object with `createTcfModel`
        tcf?:
            | {
                  tcf: Tcf;
                  tcfMetadata: TcfMetadata;
                  tcfString: string;
              }
            | BannerContext["initialState"]["tcf"];
    };
};

const BANNER_CONTEXT_SYMBOL = Symbol();
type BannerContext = ImmutableContext<{
    initialState: Pick<MainStylesheetAdditionalCustomizeProperties, "activeAction" | "pageRequestUuid4"> &
        Customize &
        CommonContextProps<{
            closeWithoutSaving: string;
            headerTitlePrivacyPolicyHistory: string;
            historyLabel: string;
            historyItemLoadError: string;
            historySelectNone: string;
            andSeparator: string;
            nonStandard: string;
            nonStandardDesc: string;
            showMore: string;
            hideMore: string;
            showLessRelevantDetails: string;
            hideLessRelevantDetails: string;
            tcf: {
                teaching: string;
                vendorList: string;
                vendors: string;
                vendorsCount: [string, string];
                dataRetentionPeriod: string;
                legIntClaim: string;
                example: string;
                filterText: string;
                filterNoVendors: string;
                standard: string;
                standardDesc: string;
                declarations: Record<
                    keyof Omit<Declarations, "stacks">,
                    {
                        title: string;
                        desc: string;
                    }
                >;
            };
        }> & {
            /**
             * Consent history management.
             */
            history?: BannerHistoryEntry[];
            visible: boolean;
            /**
             * Use this in your frontend when the overlay is server-side rendered. The server-side rendered
             * needs to have the `id` of the `pageRequestUuid4` value.
             */
            skipOverlay?: boolean;
            /**
             * Indicates whether a screen-reader user is interacting with the banner.
             * This cannot be reliably detected via user agent or navigator properties.
             * The value is set to `true` when the banner is opened and the "Skip to consent choices"
             * button (which is normally visually hidden) receives focus, as this typically only occurs
             * when navigating via keyboard or assistive technology.
             */
            isScreenReader?: boolean;
            /**
             * Indicates if the individual privacy (checkboxes, tables, ...) is open.
             */
            individualPrivacyOpen: boolean;
            languageSwitcher?: Array<LanguageSwitcherEntry>;
            /**
             * IAB vendor configuration.
             */
            tcf: {
                gvl: GVL;
                model: TCModel;
                original: Tcf;
                metadata: TcfMetadata;
            };
            /**
             * Indicates the filter for the TCF declaration.
             */
            tcfFilterBy: TcfDeclarationFilter;
            /**
             * Only needed in customize mode. When hovering the checkbox active state options, all checkboxes
             * should be simulated as "checked".
             */
            previewCheckboxActiveState?: boolean;
            /**
             * Only needed in customize mode. When hovering the menu options, the menu should be opened automatically.
             */
            previewStickyMenuOpenState?: boolean;
            /**
             * See option "Allow to choose service groups directly in the first view of the cookie banner".
             */
            didGroupFirstChange: boolean;
            /**
             * Refresh the complete site after saving the consent. This is defined in milliseconds.
             */
            refreshSiteAfterSave?: number | false;
        };
    modifiers: Partial<{
        /**
         * Banner action to open consent history.
         */
        openHistory: (e?: MouseEvent) => void;
        /**
         * Banner action to open banner.
         */
        openBanner: (e?: MouseEvent) => void;
        /**
         * Banner action to revoke consent.
         */
        revokeConsent: (successMessage?: string, e?: MouseEvent) => void;
        onLanguageSwitch: (selected: LanguageSwitcherEntry) => void;
        onSave: (markAsDoNotTrack: boolean, buttonClicked: ClickableButtonsNamed) => void;
        /**
         * Banner was visually visible, and got closed.
         */
        onClose: () => void;
        /**
         * Fetch and set the `history`.
         */
        fetchHistory: () => Promise<BannerHistoryEntry[]>;
        updateGroupChecked: (id: number, state: boolean) => void;
        updateCookieChecked: (group: number, id: number, state: boolean) => void;
        updateGcmConsentTypeChecked: (type: EServiceTemplateGoogleConsentModeTypes, state: boolean) => void;
    }>;
}>;

const useBanner: FnCreateImmutableContextForSymbol<BannerContext> = () =>
    useImmutableContext<BannerContext>(BANNER_CONTEXT_SYMBOL);

const useBannerProvider: FnCreateImmutableContextProviderForSymbol<BannerContext> = (...args) =>
    useImmutableContextProvider<BannerContext>(BANNER_CONTEXT_SYMBOL, ...args);

export {
    type ClickableButtonsNamed,
    type LanguageSwitcherEntry,
    type BannerHistoryEntry,
    type BannerContext,
    useBanner,
    useBannerProvider,
};
