import type {
    ETranslationFlag,
    ITranslatableProperties,
    ITranslated,
    ITranslationProperties,
    Prettify,
    Remove,
} from "@devowl-wp/api";
import type { EIso3166OneAlpha2, EIso3166OneAlpha2CountryGroup } from "@devowl-wp/iso-codes";

import type { IServiceTemplateDynamicField } from "./dynamic-field.js";
import type { IServiceTemplatePurpose } from "./purpose.js";
import type { IServiceTemplateTechnicalDefinition } from "./technical-definition.js";
import type { EExtendsMergeStrategy, ITemplateMetaData } from "../meta-data/meta-data.js";
import type { ITemplateMetaDataTranslatable } from "../meta-data/translatable.js";
import type { IRelease } from "../release.js";

type ServiceDataProcessingIn = EIso3166OneAlpha2 | EIso3166OneAlpha2CountryGroup;

interface IServiceTemplateTranslatable extends ITemplateMetaDataTranslatable {
    provider?: IServiceTemplateProvider;
    providerNotice?: string;
    providerPrivacyPolicyUrl?: string;
    providerLegalNoticeUrl?: string;
    groupNotice?: string;
    legalBasisNotice?: string;
    technicalHandlingNotice?: string;
    createContentBlockerNotice?: string;
    sccConclusionInstructionsNotice?: string;

    // Translation Flags 🚩
    providerTranslationFlags: ETranslationFlag[];
    providerNoticeTranslationFlags: ETranslationFlag[];
    providerPrivacyPolicyUrlTranslationFlags: ETranslationFlag[];
    providerLegalNoticeUrlTranslationFlags: ETranslationFlag[];
    groupNoticeTranslationFlags: ETranslationFlag[];
    legalBasisNoticeTranslationFlags: ETranslationFlag[];
    technicalHandlingNoticeTranslationFlags: ETranslationFlag[];
    createContentBlockerNoticeTranslationFlags: ETranslationFlag[];
    sccConclusionInstructionsNoticeTranslationFlags: ETranslationFlag[];
}

type ServiceTemplateTranslatableKeys = keyof IServiceTemplateTranslatable;

const TRANSLATABLE_SERVICE_TEMPLATE_ATTRIBUTES_LIST: ServiceTemplateTranslatableKeys[] = [
    "name",
    "headline",
    "subHeadline",
    "providerNotice",
    "groupNotice",
    "legalBasisNotice",
    "technicalHandlingNotice",
    "createContentBlockerNotice",
    "sccConclusionInstructionsNotice",
];
Object.freeze(TRANSLATABLE_SERVICE_TEMPLATE_ATTRIBUTES_LIST);

interface IServiceTemplateTranslation
    extends IServiceTemplateTranslatable,
        ITranslatableProperties,
        ITranslationProperties {}

/**
 * When extending attributes, think about WordPress client requirements: Is this field also need at WP-Client side?
 * If yes, add it to `/devowl-wp/backends/real-cookie-banner-backend/src/helper/templateExtends.ts` function `mapServiceTemplate`.
 */
interface IServiceTemplate
    extends IServiceTemplateTranslatable,
        ITranslated<IServiceTemplateTranslation>,
        ITemplateMetaData {
    group?: EServiceTemplateGroup;
    isProviderCurrentWebsite: boolean;
    legalBasis: EServiceTemplateLegalBasis;
    dataProcessingInCountries?: ServiceDataProcessingIn[];
    dataProcessingInCountriesSpecialTreatments?: EServiceTemplateDataProcessingInCountriesSpecialTreatment[];
    isEmbeddingOnlyExternalResources?: boolean;
    technicalDefinitions: IServiceTemplateTechnicalDefinition[];
    technicalDefinitionIds: string[];
    dynamicFields: IServiceTemplateDynamicField[];
    dynamicFieldIds: string[];
    purposes: IServiceTemplatePurpose[];
    purposeIds?: string[];
    executePriority?: number;
    codeOptIn?: string;
    codeOptOut?: string;
    codeOnPageLoad?: string;
    executeCodeOptInWhenNoTagManagerConsentIsGiven: boolean;
    executeCodeOptOutWhenNoTagManagerConsentIsGiven: boolean;
    deleteTechnicalDefinitionsAfterOptOut: boolean;
    googleConsentModeConsentTypes?: EServiceTemplateGoogleConsentModeTypes[];
    tagManagerOptInEventName?: string;
    tagManagerOptOutEventName?: string;
    shouldUncheckContentBlockerCheckbox?: boolean;
    shouldUncheckContentBlockerCheckboxWhenOneOf?: string[];
    release?: IRelease;
    releaseId?: string;
    purposeText?: string;
    providerText?: string;
    providerContact?: IServiceTemplateProviderContact;
    extendedMergeStrategies?: ExtendedServiceMergeStrategies;
    isCdn?: boolean;
}

type ServiceCdnState =
    | "enabled"
    | "enabledWithStandardClauses"
    | "enabledWithStandardClausesAndNotEmbeddingOnlyExternalResources"
    | "disabled";

const SERVICE_CDN_HIDDEN_CLIENT_PROPS: ServiceTemplateColumn[] = [
    "codeOnPageLoad",
    "codeOptIn",
    "codeOptOut",
    "createContentBlockerNotice",
    "deleteTechnicalDefinitionsAfterOptOut",
    "dynamicFields",
    "executeCodeOptInWhenNoTagManagerConsentIsGiven",
    "executeCodeOptOutWhenNoTagManagerConsentIsGiven",
    "googleConsentModeConsentTypes",
    "groupNotice",
    "isProviderCurrentWebsite",
    "legalBasis",
    "legalBasisNotice",
    "provider",
    "providerContact",
    "providerLegalNoticeUrl",
    "providerNotice",
    "providerPrivacyPolicyUrl",
    "providerText",
    "purposes",
    "purposeText",
    "shouldUncheckContentBlockerCheckbox",
    "shouldUncheckContentBlockerCheckboxWhenOneOf",
    "tagManagerOptInEventName",
    "tagManagerOptOutEventName",
    "technicalHandlingNotice",
];
Object.freeze(SERVICE_CDN_HIDDEN_CLIENT_PROPS);

interface IServiceTemplateLatest {
    id: string;
    latestId: string;
    latestReleasedId?: string;
    identifier: string;
}

interface IServiceTemplateProvider extends IServiceTemplateProviderContact {
    // address section
    name: string;
    streetAndNumber: string;
    placeAndPostcode: string;
    country: string;
}

interface IServiceTemplateProviderContact {
    // contact section
    email?: string;
    phone?: string;
    link?: string;
}

const EXTENDABLE_SERVICE_TEMPLATE_ATTRIBUTES_LIST = [
    "name",
    "codeOnPageLoad",
    "googleConsentModeConsentTypes",
    "codeOptIn",
    "codeOptOut",
    "createContentBlockerNotice",
    "dataProcessingInCountries",
    "dataProcessingInCountriesSpecialTreatments",
    "deleteTechnicalDefinitionsAfterOptOut",
    "dynamicFields",
    "executeCodeOptInWhenNoTagManagerConsentIsGiven",
    "executeCodeOptOutWhenNoTagManagerConsentIsGiven",
    "executePriority",
    "group",
    "groupNotice",
    "isCdn",
    "isEmbeddingOnlyExternalResources",
    "isProviderCurrentWebsite",
    "legalBasis",
    "legalBasisNotice",
    "provider",
    "providerNotice",
    "providerPrivacyPolicyUrl",
    "providerLegalNoticeUrl",
    "purposes",
    "sccConclusionInstructionsNotice",
    "shouldUncheckContentBlockerCheckbox",
    "shouldUncheckContentBlockerCheckboxWhenOneOf",
    "tagManagerOptInEventName",
    "tagManagerOptOutEventName",
    "technicalDefinitions",
    "technicalHandlingNotice",
] as Array<keyof IServiceTemplate>;
Object.freeze(EXTENDABLE_SERVICE_TEMPLATE_ATTRIBUTES_LIST);

type ExtendableServiceTemplateAttributes = Pick<
    IServiceTemplate,
    (typeof EXTENDABLE_SERVICE_TEMPLATE_ATTRIBUTES_LIST)[number]
>;

type ExtendedServiceMergeStrategies = Partial<Record<keyof ExtendableServiceTemplateAttributes, EExtendsMergeStrategy>>;

enum EServiceTemplateGroup {
    Essential = "essential",
    Functional = "functional",
    Statistics = "statistics",
    Marketing = "marketing",
}

enum EServiceTemplateLegalBasis {
    Consent = "consent",
    LegitimateInterest = "legitimate-interest",
    LegalRequirement = "legal-requirement",
}

enum EServiceTemplateDataProcessingInCountriesSpecialTreatment {
    ContractualAssurancesWithSubProcessors = "contractual-assurances-with-sub-processors",
    ProviderIsSelfCertifiedTransAtlanticDataPrivacyFramework = "provider-is-self-certified-trans-atlantic-data-privacy-framework",
    StandardContractualClauses = "standard-contractual-clauses",
    // Currently only used for TCF standard, cannot be customized in Real Cookie Banner
    BindingCorporateRules = "binding-corporate-rules",
}

enum EServiceTemplateGoogleConsentModeTypes {
    AdStorage = "ad_storage",
    AdUserData = "ad_user_data",
    AdPersonalization = "ad_personalization",
    AnalyticsStorage = "analytics_storage",
    FunctionalityStorage = "functionality_storage",
    PersonalizationStorage = "personalization_storage",
    SecurityStorage = "security_storage",
}

type IServiceTemplateClientResponse = Prettify<
    Partial<
        Remove<
            IServiceTemplate,
            | "purposes"
            | "provider"
            | "logo"
            | "logoId"
            | "extendedMergeStrategies"
            | "next"
            | "nextId"
            | "pre"
            | "preId"
            | "isDeleted"
            | "extendedTemplateId"
            | "extends"
            | "extendsId"
            | "providerText"
            | "purposeText"
            | "release"
            | "translations"
            | "successorOfIdentifier"
        > & {
            language: string;
            purpose: string;
            provider: string;
            logoUrl: string;
        }
    >
>;
type ServiceTemplateColumn = keyof IServiceTemplate;

/**
 * Represents the fields of a service template.
 * Please also have a look at TemplateMetaDataField for base fields.
 */
enum ServiceTemplateField {
    CodeOnPageLoad = "codeOnPageLoad",
    CodeOptIn = "codeOptIn",
    CodeOptOut = "codeOptOut",
    CreateContentBlockerNotice = "createContentBlockerNotice",
    CreateContentBlockerNoticeTranslationFlags = "createContentBlockerNoticeTranslationFlags",
    DataProcessingInCountries = "dataProcessingInCountries",
    DataProcessingInCountriesSpecialTreatments = "dataProcessingInCountriesSpecialTreatments",
    DeleteTechnicalDefinitionsAfterOptOut = "deleteTechnicalDefinitionsAfterOptOut",
    DynamicFields = "dynamicFields",
    DynamicFieldIds = "dynamicFieldIds",
    ExecuteCodeOptInWhenNoTagManagerConsentIsGiven = "executeCodeOptInWhenNoTagManagerConsentIsGiven",
    ExecuteCodeOptOutWhenNoTagManagerConsentIsGiven = "executeCodeOptOutWhenNoTagManagerConsentIsGiven",
    ExecutePriority = "executePriority",
    GoogleConsentModeConsentTypes = "googleConsentModeConsentTypes",
    Group = "group",
    GroupNotice = "groupNotice",
    GroupNoticeTranslationFlags = "groupNoticeTranslationFlags",
    IsCdn = "isCdn",
    IsEmbeddingOnlyExternalResources = "isEmbeddingOnlyExternalResources",
    IsProviderCurrentWebsite = "isProviderCurrentWebsite",
    LegalBasis = "legalBasis",
    LegalBasisNotice = "legalBasisNotice",
    LegalBasisNoticeTranslationFlags = "legalBasisNoticeTranslationFlags",
    Provider = "provider",
    ProviderContact = "providerContact",
    ProviderLegalNoticeUrl = "providerLegalNoticeUrl",
    ProviderLegalNoticeUrlTranslationFlags = "providerLegalNoticeUrlTranslationFlags",
    ProviderNotice = "providerNotice",
    ProviderNoticeTranslationFlags = "providerNoticeTranslationFlags",
    ProviderPrivacyPolicyUrl = "providerPrivacyPolicyUrl",
    ProviderPrivacyPolicyUrlTranslationFlags = "providerPrivacyPolicyUrlTranslationFlags",
    ProviderText = "providerText",
    ProviderTranslationFlags = "providerTranslationFlags",
    Purposes = "purposes",
    PurposeIds = "purposeIds",
    PurposeText = "purposeText",
    SccConclusionInstructionsNotice = "sccConclusionInstructionsNotice",
    SccConclusionInstructionsNoticeTranslationFlags = "sccConclusionInstructionsNoticeTranslationFlags",
    ShouldUncheckContentBlockerCheckbox = "shouldUncheckContentBlockerCheckbox",
    ShouldUncheckContentBlockerCheckboxWhenOneOf = "shouldUncheckContentBlockerCheckboxWhenOneOf",
    TagManagerOptInEventName = "tagManagerOptInEventName",
    TagManagerOptOutEventName = "tagManagerOptOutEventName",
    TechnicalDefinitions = "technicalDefinitions",
    TechnicalDefinitionIds = "technicalDefinitionIds",
    TechnicalHandlingNotice = "technicalHandlingNotice",
    TechnicalHandlingNoticeTranslationFlags = "technicalHandlingNoticeTranslationFlags",
}

const EXPORT_REMOVABLE_SERVICE: (ServiceTemplateColumn | keyof ITranslationProperties)[] = [
    "id",
    "logo",
    "logoId",
    "release",
    "releaseId",
    "extends", // only extended identifier is needed
    "next",
    "nextId",
    "pre",
    "preId",
    "extendsId",
    "translationIds",
    "extendedTemplateId",
    "translationInfo",
    "purposeIds",
    "dynamicFieldIds",
    "technicalDefinitionIds",
    "translatableRequiredFields",
    "translatedRequiredFields",
    "translatableOptionalFields",
    "translatedOptionalFields",
    "translationFlaggedFields",
    "version",
];
Object.freeze(EXPORT_REMOVABLE_SERVICE);

export {
    EServiceTemplateDataProcessingInCountriesSpecialTreatment,
    EServiceTemplateGoogleConsentModeTypes,
    EServiceTemplateGroup,
    EServiceTemplateLegalBasis,
    EXPORT_REMOVABLE_SERVICE,
    EXTENDABLE_SERVICE_TEMPLATE_ATTRIBUTES_LIST,
    type ExtendableServiceTemplateAttributes,
    type ExtendedServiceMergeStrategies,
    type IServiceTemplate,
    type IServiceTemplateClientResponse,
    type IServiceTemplateLatest,
    type IServiceTemplateProvider,
    type IServiceTemplateProviderContact,
    type IServiceTemplateTranslatable,
    type IServiceTemplateTranslation,
    type ServiceCdnState,
    type ServiceDataProcessingIn,
    type ServiceTemplateColumn,
    ServiceTemplateField,
    SERVICE_CDN_HIDDEN_CLIENT_PROPS,
    TRANSLATABLE_SERVICE_TEMPLATE_ATTRIBUTES_LIST,
};
