import type { EServiceTemplateGoogleConsentModeTypes } from "@devowl-wp/api-real-cookie-banner";
import type {
    ClickableButtonsNamed,
    CookieConsentManagerOptions,
    DecisionConsentGroups,
    ServiceTechnicalDefinition,
} from "@devowl-wp/cookie-consent-web-client";
import type { MainStylesheetAdditionalCustomizeProperties } from "@devowl-wp/web-cookie-banner";
import type { Recorder } from "@devowl-wp/web-html-element-interaction-recorder";

import type { VisualServiceGroup } from "./service.js";
import type { LazyDataForSecondView } from "../others/getLazyDataForSecondView.js";
import type { MouseEvent, ReactNode } from "react";

const CONTEXT_LATEST_DESIGN_VERSION = 12;

type TerritorialLegalBasis = "gdpr-eprivacy" | "dsg-switzerland";

type Link = {
    pageType: "legalNotice" | "privacyPolicy" | "other";
    url: string;
    hideCookieBanner?: boolean;
    /**
     * @deprecated Just used for backwards-compatibility. Should always be `true`.
     */
    isTargetBlank: boolean;
    label: string;
};

/**
 * This is different to `Customize["texts"]` as this texts are not meant to be customizable by software
 * and should not be managed by a website owner as this are strict, legal texts.
 */
type CommonContextI18nProps<AdditionalI18n = object> = {
    close: string;
    // List of texts used in cookie properties
    purpose: string;
    purposes: string;
    description: string;
    optOut: string;
    optOutDesc: string;
    provider: string;
    providerContactPhone: string;
    providerContactEmail: string;
    providerContactLink: string;
    providerPrivacyPolicyUrl: string;
    providerLegalNoticeUrl: string;
    legalBasis: {
        label: string;
        consentPersonalData: string;
        consentStorage: string;
        legitimateInterestPersonalData: string;
        legitimateInterestStorage: string;
        legalRequirementPersonalData: string;
    };
    territorialLegalBasisArticles: Record<
        TerritorialLegalBasis,
        {
            dataProcessingInUnsafeCountries: string;
        }
    >;
    legitimateInterest: string;
    consent: string;
    other: string;
    skipToConsentChoices: string;
    dataProcessingInThirdCountries: string;
    safetyMechanisms: {
        label: string;
        eu: string;
        switzerland: string;
        standardContractualClauses: string;
        adequacyDecision: string;
        bindingCorporateRules: string;
        contractualGuaranteeSccSubprocessors: string;
    };
    unknown: string;
    usesCookies: string;
    yes: string;
    no: string;
    technicalCookieName: string;
    technicalCookieDefinitions: string;
    type: string;
    host: string;
    cookieRefresh: string;
    usesNonCookieAccess: string;
    gcm: {
        teaching: string;
        purposes: Record<EServiceTemplateGoogleConsentModeTypes, string>;
        standard: string;
        standardDesc: string;
        moreInfo: string;
        moreInfoLink: string;
        dataProcessingInService: string;
    };
    duration: string;
    durationUnit: Record<`n${"1" | "x"}`, Record<`${ServiceTechnicalDefinition["durationUnit"]}`, string>>;
    noExpiration: string;
    deprecated: {
        /**
         * @deprecated Replaced by `dataProcessingInThirdCountries`
         */
        dataProcessingInUnsafeCountries: string;
        /**
         * @deprecated Replaced by `safetyMechanisms`
         */
        appropriateSafeguard: string;
        /**
         * @deprecated Replaced by `legalRequirementPersonalData`
         */
        legalRequirement: string;
    };
} & AdditionalI18n;

/**
 * This properties are used for both banner and content blocker contexts.
 */
type CommonContextProps<AdditionalI18n = object> = Pick<MainStylesheetAdditionalCustomizeProperties, "isTcf"> &
    Pick<CookieConsentManagerOptions, "isGcm"> & {
        gcmConsent?: EServiceTemplateGoogleConsentModeTypes[];
        /**
         * Defines the legal basis on which the informed consent of the cookie banner takes place. This does currently
         * support GDPR and DSG (Switzerland). In the future, there might also be a CCPA option.
         */
        territorialLegalBasis: Array<TerritorialLegalBasis>;
        /**
         * Allows you to track interactions so you can e.g. replay the interactions in a "List of consents" view.
         */
        recorder?: Recorder;
        /**
         * Determines if the current consent is a record from the database.
         */
        isConsentRecord?: boolean;
        /**
         * If this is set, the given button will be framed and marked as "clicked" (for preview purposes).
         */
        buttonClicked?: ClickableButtonsNamed;
        /**
         * None-IAB cookie groups.
         */
        groups: VisualServiceGroup[];
        /**
         * Infos about the website operator. Useful for services cofigured with `isProviderCurrentWebsite=true`.
         */
        websiteOperator: {
            address?: string;
            country?: string;
            contactEmail?: string;
            contactFormUrl?: string;
            contactPhone?: string;
        };
        links: Link[];
        consentForwardingExternalHosts?: string[];
        iso3166OneAlpha2: Record<string, string>;
        predefinedDataProcessingInSafeCountriesLists: Record<
            "GDPR" | "DSG" | "GDPR+DSG" | "ADEQUACY_EU" | "ADEQUACY_CH",
            string[]
        >;
        i18n: CommonContextI18nProps<AdditionalI18n>;
        /**
         * Render this dev notice under the buttons so you can e.g. show a label like "Sandbox system, demo purposes only".
         */
        productionNotice?: ReactNode;
        /**
         * Current consent state.
         */
        consent: DecisionConsentGroups;
        /**
         * Needed for the sticky legal links as they should only be rendered when at least one consent is given.
         */
        isConsentGiven?: boolean;
        /**
         * Persist the given consent to the database. Do not run e.g. opt-in scripts in this callback,
         * use `onApplyConsent` for this instead!
         */
        onPersistConsent: (opts: {
            consent: DecisionConsentGroups;
            gcmConsent?: CommonContextProps["gcmConsent"];
            markAsDoNotTrack?: boolean;
            buttonClicked: ClickableButtonsNamed;
            blocker?: number;
            /**
             * Only needed if there was a downloaded / dynamic embed thumbnail.
             * This information is obtained from `consent-thumbnail` and should be passed
             * as follow: `{embedId}-{fileMd5}`.
             */
            blockerThumbnail?: string;
            /**
             * Getting the encoded TCF string. As this could be a very expensive operation, this is a getter
             * function so you can easily yield the main thread in your implementation.
             */
            tcfString?: () => string;
            recorderJsonString?: string;
            uiView?: "initial" | "change";
            event?: MouseEvent;
        }) => Promise<void>;
        /**
         * The consent got persist to the database and to a cookie, so we can run our opt-in scripts.
         */
        onApplyConsent: () => Promise<void>;
        /**
         * If set, the link will be used for the powered-by link directly in the cookie banner and
         * content blocker. This link needs to be rendered server-side for SEO reasons.
         */
        poweredLink?: HTMLAnchorElement;
        /**
         * Customize the `poweredLink` with an affiliate link.
         */
        affiliate?: {
            link: string;
            labelBehind: string | false;
            description: string | false;
        };
        /**
         * See `useBannerTexts`, if this is `true` the placeholders `{{placeholder}}` are not replaced. This is useful
         * if you e.g. are using a tool like TranslatePress and want to translate the texts.
         */
        keepVariablesInTexts?: boolean;
        isDataProcessingInUnsafeCountries: boolean;
        /**
         * @deprecated Only for backwards-compatibility rendering (designVersion < 10)
         */
        dataProcessingInUnsafeCountriesSafeCountries: string[];
        isAgeNotice: boolean;
        ageNoticeAgeLimit: number;
        isListServicesNotice: boolean;
        isGcmListPurposes: boolean;
        // Currently only used in second view in cookie banner
        lazyLoadedDataForSecondView?: LazyDataForSecondView;
        fetchLazyLoadedDataForSecondView?: () => void;
        /**
         * The design version is incremented each time, we need to distinguish between some
         * UI elements within our cookie banner and content blockers. For example, in a recent
         * version of Real Cookie Banner we removed the footer for content blockers completely, but
         * to be compliant with our documentation we still want to show footers for older consents
         * in our "List of consents".
         *
         * Chronically changes:
         *
         * - **1)** Initial version
         * - **2)**
         *    - Removed footer in content blocker
         * - **3)**
         *    - Show "Accept only essential cookies" in "Change privacy settings" dialog
         *    - Show banner description teaching in content blocker
         * - **4)**
         *     - Show also essential-grouped services in list of services
         * - **5)**
         *     - Introduce special treatments for data processing in unsafe countries
         * - **6)**
         *     - Introduce accessibility (a11y)
         * - **7)**
         *     - Introduce TCF v2.2 and GVL v3 compatibility
         * - **8)**
         *     - With the introduction of the Google Consent Mode, the TCF teaching paragraph gets
         *       moved to an own paragraph.
         * - **9)**
         *     - 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)
         * - **10)**
         *     - Introduce a complete new concept of how we show data processing in unsafe countries in the frontend of the
         *       the cookie banner (https://app.clickup.com/t/86957nqtx)
         *     - When TCF and GCM is active, show GCM before TCF in the second view of the cookie banner
         * - **11)**
         *     - Introduce a new paragraph for the Google Consent Mode in the cookie banner to inform about the
         *       Google Consent Mode and the data processing purposes (https://business.safety.google/privacy/)
         * - **12)**
         *     - Introduce new labels for the "Use on legal basis of" and difference between the fact if personal data is processed
         *       and/or cookies are stored (https://app.clickup.com/t/86972222q?block=block-4dda3672-12ff-43fc-abfc-88fbf15a9d7f)
         * - Keep unset to use latest version.
         */
        designVersion: 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | typeof CONTEXT_LATEST_DESIGN_VERSION;
    };

export { CONTEXT_LATEST_DESIGN_VERSION, type CommonContextProps, type CommonContextI18nProps };
