import React from 'react';

// Isolated input for the email template name field.
// Manages its own value in local state so keystrokes only re-render this
// small component, not the entire CreativesContainer → Email → FormBuilder tree.
class TemplateNameInputField extends React.Component {
  constructor(props) {
    super(props);
    this.state = { localValue: props.initialValue || '' };
  }

  componentDidUpdate(prevProps) {
    // Sync from props only when the external value changed AND the user hasn't
    // diverged from the previous prop value. This handles async data-load in edit
    // mode without overwriting what the user is actively typing.
    if (
      prevProps.initialValue !== this.props.initialValue &&
      this.state.localValue === (prevProps.initialValue || '')
    ) {
      this.setState({ localValue: this.props.initialValue || '' });
    }
  }

  handleChange = (ev) => {
    const { value } = ev.currentTarget;
    this.setState({ localValue: value });
    if (this.props.onChange) this.props.onChange(value);
  };

  handleBlur = () => {
    if (this.props.onBlur) this.props.onBlur(this.state.localValue);
  };

  render() {
    const { onChange: _onChange, initialValue: _initialValue, onBlur: _ob, ...rest } = this.props;
    return (
      <CapInput
        {...rest}
        value={this.state.localValue}
        onChange={this.handleChange}
        onBlur={this.handleBlur}
      />
    );
  }
}
import PropTypes from 'prop-types';
import {
  CAP_SPACE_16, CAP_SPACE_32, CAP_SPACE_56, CAP_SPACE_64,
} from '@capillarytech/cap-ui-library/styled/variables';

import CapSlideBox from '@capillarytech/cap-ui-library/CapSlideBox';
import CapHeader from '@capillarytech/cap-ui-library/CapHeader';
import CapRow from '@capillarytech/cap-ui-library/CapRow';
import CapLink from '@capillarytech/cap-ui-library/CapLink';
import CapInput from '@capillarytech/cap-ui-library/CapInput';
import CapNotification from '@capillarytech/cap-ui-library/CapNotification';
import { injectIntl, FormattedMessage } from 'react-intl';
import classnames from 'classnames';
import {
  isEmpty, get, forEach, cloneDeep, debounce,
} from 'lodash';
import { connect } from 'react-redux';
import { createStructuredSelector } from 'reselect';
import { bindActionCreators, compose } from 'redux';
import styled from 'styled-components';
import { GA } from '@capillarytech/cap-ui-utils';
import { DAEMON } from '@capillarytech/vulcan-react-sdk/utils/sagaInjectorTypes';

import * as actions from './actions';
import {
  selectEmailLayout, uploadSelector, templateUserList, makeSelectTemplates,
} from '../Templates/selectors';
import SlideBoxHeader from './SlideBoxHeader';
import SlideBoxFooter from './SlideBoxFooter';
import SlideBoxContent from './SlideBoxContent';
import * as constants from './constants';
import * as commonUtil from '../../utils/common';
import { gtmPush } from '../../utils/gtmTrackers';
import './index.scss';
import * as templateActions from '../Templates/actions';
import * as globalActions from '../Cap/actions';
import * as zaloActions from '../Zalo/actions';
import { isLoading as isLoadingSelector } from './selectors';
import messages from './messages';
import zaloMessages from '../Zalo/messages';
import { MAP_TEMPLATE } from '../WeChat/Wrapper/constants';
import { makeSelectFetchingCmsData } from '../Email/selectors';
import {
  IMAGE as LINE_IMAGE, IMAGE_MAP, IMAGE_CAROUSEL, VIDEO as LINE_VIDEO, TEMPLATE, STICKER,
} from '../Line/Container/constants';
import {EXTERNAL_URL, SITE_URL, WEBPUSH_MEDIA_TYPES} from '../WebPush/constants';
import { IMAGE, VIDEO } from '../Facebook/Advertisement/constant';
import { RCS_STATUSES } from '../Rcs/constants';
import { CREATIVE } from '../Facebook/constants';
import { LOYALTY } from '../App/constants';
import {
  WHATSAPP_STATUSES, WHATSAPP_MEDIA_TYPES, PHONE_NUMBER, URL, ADD_IMAGE_URL_PREVIEW_MARKER,
} from '../Whatsapp/constants';
import { updateImagesInHtml } from '../../utils/cdnTransformation';

import injectReducer from '../../utils/injectReducer';
import injectSaga from '../../utils/injectSaga';
import creativesContainerReducer from './reducer';
import { capSagaForFetchSchemaForEntity, capSagaLiquidEntity } from '../Cap/sagas';
import { v2TemplateSagaWatchGetDefaultBeeTemplates } from '../Templates/sagas';
import { DYNAMIC_URL } from '../../v2Components/CapWhatsappCTA/constants';
import ErrorInfoNote from '../../v2Components/ErrorInfoNote';

import {
  transformChannelPayload,
  // getTemplateDiffState
} from "../../utils/transformerUtils";
import { MANUAL_CAROUSEL } from '../MobilePushNew/constants';
import { BIG_HTML } from '../InApp/constants';

/**
 * Returns true if value is "deep empty": no errors present.
 * - null/undefined: empty
 * - string: empty if length === 0
 * - array: empty if length === 0
 * - plain object (e.g. { android: [], ios: [], generic: [] }): empty only if every value is deep-empty
 */
function isDeepEmpty(value) {
  if (value == null) return true;
  if (typeof value === 'string') return value.length === 0;
  if (Array.isArray(value)) return value.length === 0;
  if (typeof value === 'object') {
    return Object.values(value).every(isDeepEmpty);
  }
  return false;
}

const classPrefix = 'add-creatives-section';
const CREATIVES_CONTAINER = 'creativesContainer';

const SlideBoxWrapper = styled.div`
  .cap-slide-box-v2-container{
    .slidebox-header, .slidebox-content-container{
      margin-bottom: ${({ slideBoxWrapperMargin }) => `${slideBoxWrapperMargin}`};
      padding: 0 rem;
      &.has-footer{
        overflow-x: hidden;
      }
    }
    .slidebox-footer{
      /* Only apply margin-bottom to footer when ErrorInfoNote is shown in footer (BEE editor) */
      /* For HTML Editor, errors are shown in ValidationErrorDisplay (inside content area), so no footer margin needed */
      margin-bottom: ${({ shouldApplyFooterMargin }) => (shouldApplyFooterMargin ? `${CAP_SPACE_16}` : '0')};
      padding: 0 rem;
      &.has-footer{
        overflow-x: hidden;
      }
    }
  }
`;
export class Creatives extends React.Component {
  constructor(props) {
    super(props);

    const initialSlidBoxContent = this.getSlideBoxContent({ mode: props.creativesMode, templateData: props.templateData, isFullMode: props.isFullMode });

    this.state = {
      isLoadingContent: true,
      templateStep: 1, //modeSelection: for template name and (for email selecting upload or editor), and createTemplate to create template create based on modeSelection
      showSlideBox: true,
      slidBoxContent: initialSlidBoxContent,
      templateData: this.getTemplateData(props.templateData),
      templateNameExists: props.creativesMode === 'edit', // if edit mode templateNameExists will be true, and false in create flow.
      currentChannel: this.props.channel || 'sms',
      weChatTemplateType: '',
      weChatMaptemplateStep: 0,
      inAppEditorType: null,
      isLiquidValidationError: false,
      errorMessages: [],
      liquidErrorMessage: {
        STANDARD_ERROR_MSG: [],
        LIQUID_ERROR_MSG: [],
      },
      activeFormBuilderTab: constants.ANDROID,
      // NEW: Test and Preview feature state
      showTestAndPreviewSlidebox: false,
      isTestAndPreviewMode: false, // Add flag to track Test & Preview mode
      // Performance optimization: Local template name for immediate UI feedback
      localTemplateName: '',
      // Track selected email create mode for new flow (HTML Editor vs Drag & Drop)
      selectedEmailCreateMode: null,
      // HTML Editor validation state (for email channel)
      htmlEditorValidationState: {
        isContentEmpty: true,
        issueCounts: { errors: 0, warnings: 0, total: 0 },
        validationComplete: false, // Flag to track if validation has completed
        errorsAcknowledged: false, // Flag to track if user has acknowledged errors by clicking redirection icon
      },
      hasPersonalizationTokenError: false, // Track personalization token errors in form
    };
    this.creativesTemplateSteps = {
      1: 'modeSelection',
      2: 'templateSelection', // only for email in current flows wil be used for mpush, line and wechat as well.
      3: 'createTemplateContent',
    };

    // Performance optimization: Debounced template name update
    this.debouncedTemplateNameUpdate = debounce(this.performTemplateNameUpdate.bind(this), 300);
  }

  componentWillUnmount() {
    if (get(this.props, 'location.query.type', '') === "embedded") {
      this.props.templateActions.resetTemplateStoreData();
    }
    this.props.globalActions.clearMetaEntities();

    // Cleanup debounced function
    if (this.debouncedTemplateNameUpdate) {
      this.debouncedTemplateNameUpdate.cancel();
    }
  }

  componentDidMount() {
    GA.timeTracker.startTimer(CREATIVES_CONTAINER);
    if (!this.props?.isFullMode) {
      this.props?.templateActions.getCdnTransformationConfig();
    }

    // Store loyalty tag props if loyaltyTagFetchingDependencies is provided
    const { loyaltyTagFetchingDependencies } = this.props;
    if (loyaltyTagFetchingDependencies) {
      this.props.actions.storeLoyaltyTagProps({ ...loyaltyTagFetchingDependencies });
    }
  }

  onEnterTemplateName = () => {
    this.setState({ templateNameExists: true });
  }

  // Performance optimized template name update
  performTemplateNameUpdate = (value, formData, onFormDataChange) => {
    const isEmptyTemplateName = !value.trim();
    const newFormData = { ...formData, 'template-name': value, 'isTemplateNameEdited': true };

    this.setState({ isTemplateNameEmpty: isEmptyTemplateName });
    onFormDataChange(newFormData);
  }

  // Update template name immediately for UI feedback
  updateTemplateNameImmediately = (value, formData, onFormDataChange) => {
    const isEmptyTemplateName = !value.trim();

    // 1. IMMEDIATE: Update local state for instant UI feedback
    this.setState({
      isTemplateNameEmpty: isEmptyTemplateName,
      localTemplateName: value,
    });

    // 2. DEBOUNCED: Only debounce the expensive onFormDataChange call
    this.debouncedTemplateNameUpdate(value, formData, onFormDataChange);
  };

  onRemoveTemplateName = () => {
    this.setState({ templateNameExists: false });
  }

  onSelectTemplate = (template, fbAdManager) => {
    const data = { slidBoxContent: constants.EDIT_TEMPLATE, templateData: template };
    if (fbAdManager) {
      data.fbAdManager = fbAdManager;
    }
    this.setState(data);
  };

  actionCallback = () => {
    CapNotification.error({
      message: <FormattedMessage {...zaloMessages.zaloFailureNotificationPreview} />,
    });
  };

  onPreviewTemplate = (template) => {
    if (template.type !== constants.ZALO) {
      const templateData = template;
      const usersList = commonUtil.getMergedUserList(this.props.templateUserList);
      const userId = parseInt(template.updatedBy, 10);
      templateData.updatedByName = commonUtil.getUserNameById(userId, usersList);
      this.setState({ slidBoxContent: constants.PREVIEW, templateData });
    } else if (get(template, 'versions.base.content.zalo.previewUrl')) {
      commonUtil.handlePreviewInNewTab(
        template.versions.base.content.zalo.previewUrl
      );
    } else {
      const {
        name = "",
        sourceAccountIdentifier = "",
        configs: { token = "" } = {},
        hostName = "",
      } = get(this.props, "Templates.selectedZaloAccount", {});
      this.props.zaloActions.getTemplateInfoById({
        username: name,
        oa_id: sourceAccountIdentifier,
        token,
        host: hostName || this.props?.hostName || this.props.Templates?.senderDetails?.hostName,
        id: template?._id,
        preview: true,
        actionCallback: this.actionCallback,
      });
    }
  };

  onEditTemplate = () => {
    if (commonUtil.hasCreativesArchivalEnabled() && this.props.templateData?.isArchived) {
      CapNotification.error({ message: this.props.intl.formatMessage(messages.cannotEditArchivedTemplate) });
      return;
    }
    this.setState({ slidBoxContent: 'editTemplate', showSlideBox: true, templateNameExists: true });
  };

  onCreateNew = (fbAdManager) => {
    const data = { slidBoxContent: 'createTemplate', showSlideBox: true };
    if (fbAdManager) {
      data.fbAdManager = fbAdManager;
    }
    this.setState(data);
  };

  onShowTemplates = () => {
    this.setState({
      slidBoxContent: 'templates',
      showSlideBox: true,
      isGetFormData: false,
      liquidErrorMessage: { STANDARD_ERROR_MSG: [], LIQUID_ERROR_MSG: [] },
      isLiquidValidationError: false,
    });
    this.resetStep();
  };

  onChannelChange = (channel) => {
    this.setState({
      currentChannel: channel,
      templateData: null,
      liquidErrorMessage: { STANDARD_ERROR_MSG: [], LIQUID_ERROR_MSG: [] },
      isLiquidValidationError: false,
    });
  }

  onCreateNextStep = () => {
    this.setState((prevState) => {
      let templateStep = prevState.templateStep + 1;
      const { emailCreateMode, currentChannel, selectedEmailCreateMode } = prevState;

      // Check if we should skip template selection for HTML Editor
      const supportCKEditor = commonUtil.hasSupportCKEditor();
      const shouldSkipTemplateSelection = !supportCKEditor
        && selectedEmailCreateMode === 'html_editor'
        && currentChannel.toUpperCase() === constants.EMAIL
        && prevState.templateStep === 1; // Only skip if we're at modeSelection step

      if (shouldSkipTemplateSelection) {
        // Skip template selection (step 2), go directly to createTemplateContent (step 3)
        templateStep = prevState.templateStep + 2;
      } else if ((currentChannel.toUpperCase() === constants.EMAIL && emailCreateMode === "upload") || [constants.MOBILE_PUSH, constants.WECHAT, constants.INAPP].includes(currentChannel.toUpperCase())) {
        templateStep = prevState.templateStep + 2;
      }
      return {
        templateStep,
      };
    });
  }

  onEmailModeChange = (mode, selectedMode = null) => {
    this.setState({
      emailCreateMode: mode,
      selectedEmailCreateMode: selectedMode || mode, // Store the selected mode for new flow
    });
  }

  onInAppModeChange = (mode) => {
    this.setState({ inAppCreateMode: mode });
  }

  onInAppEditorTypeChange = (editorType) => {
    this.setState({ inAppEditorType: editorType });
  }

  onMobilepushModeChange = (mode) => {
    this.setState({ mobilePushCreateMode: mode });
  }

  onWechatTemplateChange = (templateType) => {
    this.setState({ weChatTemplateType: templateType });
  }

  onWeChatMaptemplateStepChange = (step) => {
    this.setState({ weChatMaptemplateStep: step });
  }

  onCallTaskSubmit = (data) => {
    this.props.getCreativesData({
      channel: 'CALL_TASK',
      ...data,
    });
  };

  onValidationFail = () => {
    this.setState({ isGetFormData: false });
  };

  mapCarouselDataToCreatives = (cards) => cards.map((card) => {
    const {
      cardVarMapped, bodyTemplate, media, buttons, mediaType,
    } = card || {};
    const buttonData = buttons?.map((button) => {
      const {
        type, text, phoneNumber, url, dynamicUrlPayload,
      } = button || {};
      const buttonObj = { type, text };
      if (type === PHONE_NUMBER) {
        buttonObj.phone_number = phoneNumber;
      }
      if (type === URL) {
        buttonObj.url = url;
        if (dynamicUrlPayload) {
          buttonObj.urlType = DYNAMIC_URL;
        }
      }
      return buttonObj;
    });
    const { url, previewUrl } = media || {};
    return {
      bodyText: bodyTemplate,
      varMap: cardVarMapped,
      ...(mediaType === IMAGE && {
        imageUrl: url,
      }),
      ...(mediaType === VIDEO && {
        videoUrl: url,
        videoPreviewImg: previewUrl,
      }),
      buttons: buttonData,
      mediaType: mediaType?.toLowerCase(),
    };
  })

  getTemplateData = (templateData) => { //from consumers to creatives
    const { isFullMode, messageDetails = {}, smsRegister } = this.props;
    const { additionalProperties = {} } = messageDetails;
    if (!isFullMode && templateData) { // for component mode
      const { channel } = templateData;
      let creativesTemplateData = { type: channel };
      switch (channel) {
        case constants.NO_COMMUNICATION: {
          creativesTemplateData = {
            type: channel,
            ...templateData,
          };
          break;
        }
        case constants.SMS: {
          const isTraiDlt = commonUtil.isTraiDLTEnable(isFullMode, smsRegister);
          let formData = {};
          if (isTraiDlt) {
            const {
              template_id = '',
              header = '',
              template_name = '',
              'sms-editor': smsEditor = '',
              'var-mapped': varMapped = {},
            } = templateData;
            formData = {
              template_id,
              header,
              template_name,
              'sms-editor': smsEditor,
              'var-mapped': varMapped,
            };
          } else {
            formData = {
              'sms-editor': templateData.messageBody,
            };
          }
          creativesTemplateData = {
            type: channel,
            name: "Campaign message SMS content",
            versions: {
              base: formData,
              history: [formData],
            },
          };
          break;
        }
        case constants.EMAIL: {
          const formData = {
            subject: templateData.emailSubject,
            html_content: templateData.emailBody,
            is_drag_drop: templateData.is_drag_drop,
            lang_id: templateData.lang_id,
            iso_code: templateData.iso_code,
            language: templateData.language,
            drag_drop_id: templateData.drag_drop_id,
            json_content: templateData.json_content,
            id: templateData.id,
          };
          creativesTemplateData = {
            base: formData,
            edit: true,
            type: channel,
          };
          break;
        }
        case constants.CALL_TASK: {
          creativesTemplateData = {
            subject: templateData && templateData.subject,
            messageBody: templateData && templateData.messageBody,
            description: templateData && templateData.description,
            edit: true,
            type: channel,
          };
          break;
        }
        case constants.MOBILE_PUSH: {
          const mode = get(templateData, 'androidContent.type') || get(templateData, 'iosContent.type') || '';
          const androidCarouselMedia = get(templateData, 'androidContent.expandableDetails.media', []);
          const iosCarouselMedia = get(templateData, 'iosContent.expandableDetails.media', []);
          const androidContent = { ...(templateData?.androidContent || {}) };
          const iosContent = { ...(templateData?.iosContent || {}) };
          if (androidCarouselMedia?.length) {
            androidContent.expandableDetails.carouselData = androidCarouselMedia.map((media) => ({
              mediaType: media?.type,
              imageUrl: media?.url,
              buttons: [],
              videoSrc: '',
            }));
          }
          if (iosCarouselMedia?.length) {
            iosContent.expandableDetails.carouselData = iosCarouselMedia.map((media) => ({
              mediaType: media?.type,
              imageUrl: media?.url,
              buttons: [],
              videoSrc: '',
            }));
          }
          creativesTemplateData = {
            type: channel,
            name: templateData.messageSubject,
            versions: {
              base: {
                ANDROID: androidContent,
                IOS: iosContent,
              },
            },
            definition: { accountId: templateData.accountId, mode: mode.toLowerCase() },
          };
          break;
        }
        case constants.INAPP: {
          const mode = get(templateData, 'androidContent.type') || get(templateData, 'iosContent.type') || '';

          // Check if this is a BEE editor template (identified by special title 'bee free template')
          const isAndroidBeeEditor = templateData?.androidContent?.type === constants.HTML
            && templateData?.androidContent?.title?.toLowerCase() === 'bee free template';
          const isIosBeeEditor = templateData?.iosContent?.type === constants.HTML
            && templateData?.iosContent?.title?.toLowerCase() === 'bee free template';

          creativesTemplateData = {
            type: channel,
            name: templateData.messageSubject,
            versions: {
              base: {
                content: {
                  ANDROID: isAndroidBeeEditor ? {
                    type: templateData?.androidContent?.type,
                    bodyType: templateData?.androidContent?.bodyType,
                    deviceType: constants.ANDROID,
                    beeHtml: { value: templateData?.androidContent?.message },
                    beeJson: templateData?.androidContent?.expandableDetails?.message,
                    isBEEeditor: true,
                  } : templateData?.androidContent,
                  IOS: isIosBeeEditor ? {
                    type: templateData?.iosContent?.type,
                    bodyType: templateData?.iosContent?.bodyType,
                    deviceType: constants.IOS,
                    beeHtml: { value: templateData?.iosContent?.message },
                    beeJson: templateData?.iosContent?.expandableDetails?.message,
                    isBEEeditor: true,
                  } : templateData?.iosContent,
                },
              },
            },
            definition: { accountId: templateData?.accountId, mode: mode?.toLowerCase() },
          };
          break;
        }
        case constants.WECHAT: {
          const messageBody = JSON.parse(templateData.messageBody);
          creativesTemplateData = {
            ...messageBody.data,
            type: channel,
            _id: messageBody.template_id,
            isEditFromCampaigns: true,
          };
          break;
        }
        case constants.FACEBOOK: {
          if (templateData.fbContentType === CREATIVE) {
            const {
              creativeType = "",
              selectedFacebookAccount = {},
              facebookCreativeList: fbCreativeList = [],
              fbContentType,
            } = templateData || {};
            const fBContent = fbCreativeList;
            const facebookCreativeList = [];
            fBContent.forEach((obj) => {
              const data = cloneDeep(obj);
              const {
                subType, linkDescription, imageLink, websiteLink, videoId, videoName, videoUrl,
              } = obj || {};
              delete data.linkDescription;
              delete data.websiteLink;
              data.linkDesc = linkDescription;
              data.webSiteLink = websiteLink;
              data.type = creativeType;
              switch (subType) {
                case IMAGE:
                  data.imgSrc = imageLink;
                  delete data.imageLink;
                  break;
                case VIDEO:
                  data.video = {
                    previewImageUrl: imageLink,
                    videoId,
                    originalContentUrl: videoUrl,
                    videoName,
                  };
                  delete data.imageLink;
                  break;
                default:
                  break;
              }
              facebookCreativeList.push(data);
            });
            creativesTemplateData = {
              versions: {
                base: {
                  content: {
                    FacebookAd: { ...facebookCreativeList },
                    pageOrgUnitId: this.props.orgUnitId,
                  },
                },
              },
              type: constants.FACEBOOK,
              edit: true,
              selectedFacebookAccount,
              fbContentType,
            };
          } else {
            creativesTemplateData = {
              selectedMarketingObjective: templateData.selectedMarketingObjective,
              edit: true,
              type: channel,
              fbContentType: templateData.fbContentType,
            };
          }
          break;
        }
        case constants.LINE: {
          const { messageBody, isDefault } = templateData;
          const { messages = '[]' } = additionalProperties;
          const messagesDefinition = JSON.parse(messages);
          let lineContent = JSON.parse(messageBody || '{}').messages || [{}];
          lineContent = lineContent.map((content, index) => ({
            ...content,
            ...(messagesDefinition[index] || {}),
          }));
          creativesTemplateData = {
            type: constants.LINE,
            isDefault,
            edit: true,
            definition: {
              mode: constants.LINE,
            },
            name: "Campaign message Line content",
            versions: {
              base: {
                content: {
                  messages: lineContent,
                  to: "{{line_id}}",
                },
              },
            },
          };
          break;
        }
        case constants.VIBER: {
          const { messageBody, isDefault } = templateData;
          const viber = JSON.parse(messageBody || '{}');
          creativesTemplateData = {
            type: constants.VIBER,
            isDefault,
            edit: true,
            name: "",
            versions: {
              base: {
                content: {
                  ...viber,
                },
              },
            },
          };
          break;
        }
        case constants.WHATSAPP:
        case constants.WHATSAPP?.toLowerCase(): {
          const {
            messageBody = '',
            templateConfigs: {
              name,
              template,
              varMapped,
              category,
              language,
              templateId,
              buttonType = 'NONE',
              buttons = [],
              mediaType = 'TEXT',
              whatsappMedia = {},
              isPreviewUrl = false,
              cards = [],
              id = '',
            } = {},
          } = templateData;
          const mediaParams = {};
          const {
            url = '', previewUrl = '', docParams = {}, footer = '', headerVarMapped = {}, headerTemplate = '',
          } = whatsappMedia || {};
          switch (mediaType) {
            case (WHATSAPP_MEDIA_TYPES.IMAGE):
              mediaParams.imageUrl = url;
              // Detect isAddImageUrl from previewUrl marker (previewUrl is unused for IMAGE type)
              mediaParams.isAddImageUrl = previewUrl === ADD_IMAGE_URL_PREVIEW_MARKER;
              break;
            case (WHATSAPP_MEDIA_TYPES.VIDEO):
              mediaParams.videoUrl = url;
              mediaParams.videoPreviewImg = previewUrl;
              break;
            case (WHATSAPP_MEDIA_TYPES.DOCUMENT):
              mediaParams.documentUrl = url;
              mediaParams.whatsappDocParams = {
                ...docParams,
                whatsappDocImg: previewUrl,
              };
              break;
            default:
              break;
          }
          const modifiedButtons = cloneDeep(buttons)?.map((btn) => {
            if (btn.type === PHONE_NUMBER) {
              btn.phone_number = btn.phoneNumber;
              delete btn.phoneNumber;
              return btn;
            }
            return btn;
          });
          for (const key in varMapped) {
            if (key.includes('_unsubscribe')) {
              delete varMapped[key];
            }
          }
          const unsubscribeRegex = /Click {{unsubscribe}} to unsubscribe/g;
          creativesTemplateData = {
            _id: id,
            type: constants.WHATSAPP,
            edit: true,
            name,
            versions: {
              base: {
                content: {
                  whatsapp: {
                    status: WHATSAPP_STATUSES.approved,
                    category,
                    varMapped,
                    mediaType,
                    templateId,
                    ...mediaParams,
                    buttonType,
                    buttons: modifiedButtons,
                    whatsappMedia: {
                      header: headerTemplate,
                      footer,
                      headerVarMapped,
                    },
                    languages: [
                      {
                        language,
                        content:
                          messageBody.match(unsubscribeRegex)?.length > 0
                            ? `${template}\nClick {{unsubscribe}} to unsubscribe`
                            : template,
                      },
                    ],
                    isPreviewUrl,
                    carouselData: this.mapCarouselDataToCreatives(cards),
                    ...(cards?.length && {
                      mediaType: WHATSAPP_MEDIA_TYPES.CAROUSEL,
                    }),
                  },
                },
              },
            },
          };
          break;
        }
        case constants.RCS: {
          const {
            rcsContent = {},
            smsFallBackContent = {},
            creativeName = "",
            channel = constants.RCS,
            accountId = "",
          } = templateData || {};
          const cardContent = (rcsContent.cardContent && rcsContent.cardContent[0]) || {};
          const Status = RCS_STATUSES.approved || '';

          creativesTemplateData = {
            type: channel,
            edit: true,
            name: creativeName,
            versions: {
              base: {
                content: {
                  RCS: {
                    rcsContent: {
                      ...rcsContent,
                      ...(accountId && !isFullMode && { accountId }),
                      cardContent: [
                        {
                          ...cardContent,
                          Status,
                        },
                      ],
                    },
                    smsFallBackContent,
                  },
                },
              },
            },
          };
          break;
        }
        case constants.ZALO: {
          creativesTemplateData = {
            type: constants.ZALO,
            ...templateData,
          };
          break;
        }
        case constants.WEBPUSH: {
          // Convert from campaign format (messageContent.content.content) to creatives format
          const webpushContent = get(templateData, 'content', {});
          const accountId = get(templateData, 'accountId');
          const { 
            title, 
            message, 
            iconImageUrl: brandIcon = "", 
            cta, 
            expandableDetails 
          } = webpushContent || {};
          
          // Map cta to onClickAction
          let onClickAction = null;
          if (cta) {
            if (cta?.type === EXTERNAL_URL) {
              onClickAction = {
                type: URL,
                url: cta?.actionLink || '',
              };
            } else {
              onClickAction = {
                type: cta?.type || SITE_URL,
              };
            }
          }
          
          // Map expandableDetails.ctas to ctas array
          let ctas = [];
          if (expandableDetails?.ctas && expandableDetails?.ctas?.length > 0) {
            ctas = expandableDetails?.ctas?.map((ctaItem) => ({
              actionText: ctaItem?.title || ctaItem?.actionText || '',
              type: URL,
              actionLink: ctaItem?.actionLink || '',
            }));
          }
          
          // Map expandableDetails.media to image if present
          let image = null;
          if (expandableDetails?.media && expandableDetails?.media?.length > 0) {
            const firstMedia = expandableDetails?.media[0];
            if (firstMedia?.type === WEBPUSH_MEDIA_TYPES.IMAGE && firstMedia?.url) {
              image = firstMedia?.url;
            }
          }
          
          creativesTemplateData = {
            type: channel,
            name: templateData?.messageSubject,
            versions: {
              base: {
                content: {
                  webpush: {
                    title: title || '',
                    message: message || '',
                    ...(brandIcon && { brandIcon }),
                    ...(onClickAction && { onClickAction }),
                    ...(ctas.length > 0 && { ctas }),
                    ...(image && { image, mediaType: IMAGE }),
                  },
                },
              },
            },
            definition: { accountId },
          };
          break;
        }
        default:
          break;
      }
      return creativesTemplateData;
    }
    return templateData || null;
  }

  getCarouselMappedData = (carouselData = []) => carouselData.map((carousel) => {
    const {
      bodyText, imageUrl, videoUrl, videoPreviewImg, buttons, mediaType, cardVarMapped, bodyTemplate,
    } = carousel || {};
    const buttonData = buttons.map((button, index) => {
      const {
        type, text, phone_number, urlType, url,
      } = button || {};
      const buttonObj = {
        type,
        text,
        index,
      };
      if (type === PHONE_NUMBER) {
        buttonObj.phoneNumber = phone_number;
      }
      if (type === URL) {
        buttonObj.url = url;
        if (urlType === DYNAMIC_URL) {
          const dynamicUrlPayload = url?.match(/{{(.*?)}}/g);
          buttonObj.dynamicUrlPayload = dynamicUrlPayload?.length === 1 ? dynamicUrlPayload[0] : '';
        }
      }
      return buttonObj;
    });
    return {
      body: bodyText,
      cardVarMapped,
      bodyTemplate,
      media: {
        ...(mediaType?.toLowerCase() === IMAGE.toLowerCase() && {
          url: imageUrl,
        }),
        ...(mediaType?.toLowerCase() === VIDEO.toLowerCase() && {
          url: videoUrl,
          previewUrl: videoPreviewImg,
        }),
      },
      buttons: buttonData,
      mediaType: mediaType?.toUpperCase(),
    };
  });

  getMobilePushCarouselData = (expandableDetails = []) => {
    const newExpandableDetails = { ...expandableDetails };
    newExpandableDetails.style = expandableDetails.style || MANUAL_CAROUSEL;
    newExpandableDetails.message = expandableDetails.message || '';
    newExpandableDetails.ctas = expandableDetails.ctas || [];
    newExpandableDetails.media = expandableDetails.carouselData.map((carousel) => ({
      url: carousel.imageUrl,
      type: carousel?.mediaType?.toUpperCase(),
      text: '',
    }));
    return newExpandableDetails;
  }

  getCreativesData = async (channel, template, templateRecords) => { //from creatives to consumers
    let templateData = { channel };
    switch (channel) {
      case constants.SMS:
        if (template?.value?.base) {
          const smsBase = template.value.base || {};
          const { isFullMode, smsRegister } = this.props;
          const isTraiDlt = commonUtil.isTraiDLTEnable(isFullMode, smsRegister);
          const {
            'updated-sms-editor': updatedSmsEditor,
            'sms-editor': smsEditor,
          } = smsBase;
          if (!isTraiDlt) {
            templateData.messageBody = smsEditor;
          } else {
            templateData.messageBody = updatedSmsEditor === "" ? smsEditor : updatedSmsEditor.join('');
            const {
              template_id,
              template_name,
              header,
              'var-mapped': varMapped,
            } = smsBase;
            templateData.templateConfigs = {
              templateId: template_id,
              templateName: template_name,
              template: smsEditor,
              registeredSenderIds: header,
              templateVariableMapping: varMapped,
            };
          }
        }
        break;
      case constants.EMAIL:
        if (template?.value?.base) {
          let emailBase = template.value.base;
          const { html_content } = emailBase || {};
          if (!html_content) {
            emailBase = templateRecords.base;
          }
          const newHtmlContent = await updateImagesInHtml(html_content);
          templateData = {
            ...templateData, ...emailBase, emailBody: newHtmlContent, emailSubject: (emailBase && emailBase.subject) ? emailBase.subject : '',
          };
          delete templateData.html_content;
          delete templateData.subject;
        }
        break;
      case constants.MOBILE_PUSH:
      case constants.INAPP:
        if (get(template, "value.versions.base")) {
          const channelTemplate = template.value;
          templateData.accountId = get(channelTemplate, 'definition.accountId');
          const type = (get(this.props, "messageDetails.type") || '').toLowerCase();
          const sourceType = get(channelTemplate, 'definition.sourceType');
          if (type === LOYALTY) {
            if (sourceType === 'MAPP_SDK') {
              templateData.templateId = get(channelTemplate, '_id');
              templateData.licenseCode = get(channelTemplate, 'definition.licenseCode');
              templateData.gatewayId = get(channelTemplate, 'definition.gatewayId');
              templateData.gatewayAccountId = get(channelTemplate, 'definition.gatewayAccountId');
              templateData.sourceType = get(channelTemplate, 'definition.sourceType');
            } else {
              templateData.templateId = get(channelTemplate, '_id');
              templateData.licenseCode = get(channelTemplate, 'definition.licenseCode');
              templateData.sourceType = get(channelTemplate, 'definition.sourceType');
            }
          }
          const androidContent = channel === constants.INAPP ? get(channelTemplate, 'versions.base.content.ANDROID') : get(channelTemplate, 'versions.base.ANDROID');
          if (!isEmpty(androidContent)) {
            if (type !== LOYALTY) {
              delete androidContent.cuid;
              delete androidContent.luid;
              delete androidContent.communicationId;
            }
            const custom = {};
            forEach(androidContent.custom, (customKeyValue) => {
              custom[customKeyValue.key] = customKeyValue.value;
            });
            //skipping it for MPUSH as custom key is already in the reqd format for hydra sdk
            if (channel !== constants.MOBILE_PUSH) {
              androidContent.custom = custom;
            }
            if (channel === constants.MOBILE_PUSH && androidContent?.expandableDetails?.carouselData?.length) {
              androidContent.expandableDetails = this.getMobilePushCarouselData({ ...androidContent?.expandableDetails });
            }
            if (androidContent?.isBEEeditor && androidContent?.beeHtml?.value) {
              templateData.androidContent = {};
              templateData.androidContent.type = constants.HTML;
              templateData.androidContent.message = androidContent?.beeHtml?.value || '';
              templateData.androidContent.title = 'bee free template';
              templateData.androidContent.bodyType = androidContent?.bodyType;
              templateData.androidContent.deviceType = constants.ANDROID;
              templateData.androidContent.expandableDetails = {
                style: BIG_HTML,
                message: androidContent?.beeJson || '',
              };
            } else if (!androidContent?.isBEEeditor) {
              templateData.androidContent = androidContent;
              templateData.androidContent.type = androidContent?.type || get(channelTemplate, 'definition.mode', '')?.toUpperCase() || constants.TEXT;
              templateData.androidContent.deviceType = constants.ANDROID;
            }
          }
          const iosContent = channel === constants.INAPP ? get(channelTemplate, 'versions.base.content.IOS') : get(channelTemplate, 'versions.base.IOS');
          if (!isEmpty(iosContent)) {
            if (type !== LOYALTY) {
              delete iosContent.cuid;
              delete iosContent.luid;
              delete iosContent.communicationId;
            }
            const custom = {};
            forEach(iosContent.custom, (customKeyValue) => {
              custom[customKeyValue.key] = customKeyValue.value;
            });
            //skipping it for MPUSH as custom key is already in the reqd format for hydra sdk
            if (channel !== constants.MOBILE_PUSH) {
              iosContent.custom = custom;
            }
            if (channel === constants.MOBILE_PUSH && iosContent?.expandableDetails?.carouselData?.length) {
              iosContent.expandableDetails = this.getMobilePushCarouselData({ ...iosContent?.expandableDetails });
            }
            if (iosContent?.isBEEeditor && iosContent?.beeHtml?.value) {
              templateData.iosContent = {};
              templateData.iosContent.type = constants.HTML;
              templateData.iosContent.message = iosContent?.beeHtml?.value || '';
              templateData.iosContent.title = 'bee free template';
              templateData.iosContent.bodyType = iosContent?.bodyType;
              templateData.iosContent.deviceType = constants.IOS;
              templateData.iosContent.expandableDetails = {
                style: BIG_HTML,
                message: iosContent?.beeJson || '',
              };
            } else if (!iosContent?.isBEEeditor) {
              templateData.iosContent = iosContent;
              templateData.iosContent.type = iosContent?.type || get(channelTemplate, 'definition.mode', '')?.toUpperCase() || 'TEXT';
              templateData.iosContent.deviceType = constants.IOS;
            }
          }
          templateData.messageSubject = channelTemplate?.name ? channelTemplate?.name : "messageSubject";
        }
        break;
      case constants.WECHAT:
        if (template.value) {
          const { accountId, previewContent, ...messageBody } = template.value;
          templateData = {
            channel, accountId, messageBody: JSON.stringify(messageBody), previewContent,
          };
        }
        break;
      case constants.LINE:
        if (template.value) {
          const { versions } = template.value;
          const { Templates, templateData: templateDataProps } = this.props;
          const { accountDetails: selectedAccountDetails, accountId: selectedAccountId } = templateDataProps || {};
          const selectedLineAccount = Templates && Templates.selectedLineAccount;
          const accountDetails = selectedAccountDetails || (selectedLineAccount ? JSON.stringify(selectedLineAccount) : '');
          const accountId = selectedAccountId || (selectedLineAccount ? selectedLineAccount.id : '');
          templateData = {
            channel,
            accountId,
            accountDetails,
            messageBody: JSON.stringify(versions.base.content),
          };
        }
        break;
      case constants.VIBER:
        if (template.value) {
          const { Templates, templateData: templateDataProps } = this.props;
          const { accountDetails: selectedAccountDetails, accountId: selectedAccountId } = templateDataProps || {};
          const selectedViberAccount = Templates && Templates.selectedViberAccount;
          const accountDetails = (selectedViberAccount ? JSON.stringify(selectedViberAccount) : selectedAccountDetails);
          const accountId = selectedAccountId || (selectedViberAccount ? selectedViberAccount.id : '');
          const { versions } = template.value;
          const content = cloneDeep(versions.base.content);
          content.scenarioKey = accountDetails ? get(JSON.parse(accountDetails), 'configs.scenario_key') : "";
          templateData = {
            channel,
            accountId,
            accountDetails,
            messageBody: JSON.stringify(content),
          };
        }
        break;
      case constants.WHATSAPP:
        if (template.value) {
          const { Templates, templateData: templateDataProps } = this.props;
          const selectedWhatsappAccount = Templates?.selectedWhatsappAccount;
          const { accountDetails: selectedAccountDetails, accountId: selectedAccountId } = templateDataProps || {};
          const accountDetails = (selectedWhatsappAccount || selectedAccountDetails);
          const accountId = selectedAccountId || (selectedWhatsappAccount?.id || '');
          const { versions } = template.value;
          const {
            languages = [{}],
            mediaType = 'TEXT',
            category = '',
            templateEditor = '',
            varMapped = {},
            buttonType = 'NONE',
            buttons = [],
            imageUrl = '',
            templateId = '',
            videoUrl = '',
            documentUrl = '',
            videoPreviewImg = '',
            whatsappDocParams = {},
            whatsappMedia: {
              header = '',
              headerVarMapped = {},
              footer = '',
              headerTemplate = '',
            } = {},
            isPreviewUrl = false,
            isAddImageUrl = false,
            carouselData = [],
          } = cloneDeep(versions.base.content.whatsapp);

          const modifiedButtons = cloneDeep(buttons).map((btn) => {
            if (btn.type === 'PHONE_NUMBER') {
              btn.phoneNumber = btn.phone_number;
              delete btn.phone_number;
            } else if (btn.type === 'DYNAMIC_URL') {
              const dynamicUrlPayload = btn.url.match(/{{(.*?)}}/g);
              btn.dynamicUrlPayload = dynamicUrlPayload.length === 1 ? dynamicUrlPayload[0] : '';
            }
            return btn;
          });

          //to send {{unsubscribe}} to backend inside varMapped
          const unsubscribeRegex = /Click {{unsubscribe}} to unsubscribe/g;
          if (
            languages[0].content?.match(unsubscribeRegex)?.length > 0
            && Object.keys(varMapped)?.every(
              (key) => !key?.includes("_unsubscribe")
            )
          ) {
            varMapped[`{{${Object.keys(varMapped).length + 1}}}_unsubscribe`] = "{{unsubscribe}}";
          }
          const whatsappMedia = {
            header,
            footer,
            headerVarMapped,
            headerTemplate,
          };
          const {
            whatsappDocName = '', whatsappDocSize, whatsappDocPages, whatsappDocImg = '',
          } = whatsappDocParams;
          switch (mediaType) {
            case (WHATSAPP_MEDIA_TYPES.IMAGE):
              whatsappMedia.url = imageUrl;
              // previewUrl is unused for IMAGE type — reuse it to persist isAddImageUrl flag
              // without adding any new field that the backend would reject
              if (isAddImageUrl) {
                whatsappMedia.previewUrl = ADD_IMAGE_URL_PREVIEW_MARKER;
              }
              break;
            case (WHATSAPP_MEDIA_TYPES.VIDEO):
              whatsappMedia.url = videoUrl;
              whatsappMedia.previewUrl = videoPreviewImg;
              break;
            case (WHATSAPP_MEDIA_TYPES.DOCUMENT):
              whatsappMedia.url = documentUrl;
              whatsappMedia.previewUrl = whatsappDocImg;
              whatsappMedia.docParams = {
                whatsappDocName,
                whatsappDocSize,
                whatsappDocPages,
              };
              break;
            default:
              break;
          }

          templateData = {
            channel,
            accountId,
            sourceAccountIdentifier: selectedWhatsappAccount?.sourceAccountIdentifier || '',
            accountName: accountDetails?.name || '',
            messageBody: languages[0].content,
            templateConfigs: {
              id: template?._id,
              name: template?.value?.name,
              template: templateEditor,
              varMapped,
              templateId,
              category,
              language: languages[0].language,
              ...(mediaType !== WHATSAPP_MEDIA_TYPES.CAROUSEL && {
                buttonType,
                buttons: modifiedButtons,
                whatsappMedia,
              }),
              mediaType,
              isPreviewUrl,
              ...(mediaType === WHATSAPP_MEDIA_TYPES.CAROUSEL && {
                cards: this.getCarouselMappedData(carouselData),
                mediaType: carouselData[0]?.mediaType?.toUpperCase(),
              }),
            },
          };
        }
        break;
      case constants.FACEBOOK:
        if (template.value) {
          const FacebookAd = template?.value?.versions?.base?.content?.FacebookAd;
          const { type } = FacebookAd[0];
          const { accountId } = this.props.Templates.selectedFacebookAccount || template.value || {};
          const facebookCreativeList = [];
          const fBContent = Object.values(FacebookAd);
          fBContent.forEach((obj) => {
            const data = cloneDeep(obj);
            const {
              subType, linkDesc, imgSrc, webSiteLink, video,
            } = obj;
            delete data.type;
            delete data.linkDesc;
            delete data.webSiteLink;
            data.linkDescription = linkDesc;
            data.websiteLink = webSiteLink;

            switch (subType) {
              case IMAGE:
                data.imageLink = imgSrc;
                delete data.imgSrc;
                break;
              case VIDEO:
                data.imageLink = video.previewImageUrl;
                data.videoId = video.videoId;
                data.videoUrl = video.originalContentUrl;
                data.videoName = video.videoName;
                delete data.video;
                break;
              default:
                break;
            }
            facebookCreativeList.push(data);
          });
          templateData = {
            fbContentType: CREATIVE,
            creativeType: type,
            facebookCreativeList,
            channel: constants.FACEBOOK,
            accountId,
            selectedMarketingObjective: template.value.selectedMarketingObjective,
          };
        }
        break;
      case constants.RCS:
        if (template.value) {
          const { name = "", versions = {} } = {
          } = template.value || {};
          const smsFallBackContent = get(versions, 'base.content.RCS.smsFallBackContent', {});
          const {
            cardContent = [],
            contentType = "",
            cardType = "",
            cardSettings = {},
            accountId = "",
          } = get(versions, 'base.content.RCS.rcsContent', {});
          const rcsContent = {
            contentType,
            cardType,
            cardSettings,
            cardContent,
          };
          templateData = {
            channel,
            creativeName: name,
            rcsContent,
            accountId,
          };
        }
        break;
      case constants.ZALO:
        if (template.value) {
          templateData = {
            ...template.value,
          };
          if (templateData?.type) {
            delete templateData.type;
          }
        }
        break;
      case constants.WEBPUSH: {
        if (template.value) {
          const channelTemplate = template.value;
          const accountId = get(channelTemplate, 'definition.accountId');
          const webpushContent = get(channelTemplate, 'versions.base.content.webpush', {});
          const { 
            title, 
            message, 
            brandIcon, 
            iconImageUrl: templateImageUrl , 
            onClickAction, 
            ctas: templateCtas, 
            cta: templateCta, 
            expandableDetails: templateExpandableDetails, 
            image 
          } = webpushContent || {};
          
          const iconImageUrl = brandIcon || templateImageUrl || '';
          
          // Map onClickAction to cta
          let cta = null;
          if (onClickAction) {
            if (onClickAction?.type === URL) {
              cta = {
                type: EXTERNAL_URL,
                actionLink: onClickAction?.url || '',
              };
            } else {
              cta = {
                type: onClickAction?.type || SITE_URL,
                actionLink: onClickAction?.url || '',
              };
            }
          } else if (templateCta) {
            // Fallback to cta if onClickAction is not present
            cta = {
              type: templateCta?.type || EXTERNAL_URL,
              actionLink: templateCta?.actionLink || '',
            };
          }
          
          // Map ctas array to expandableDetails.ctas
          let expandableDetails = null;
          const hasCtas = templateCtas && templateCtas.length > 0;
          const hasImage = image;
          
          if (hasCtas || hasImage) {
            expandableDetails = {
              media: [],
              ctas: [],
            };
            
            // Map image to expandableDetails.media
            if (hasImage) {
              expandableDetails.media = [{
                url: image,
                type: IMAGE,
              }];
            }
            
            // Map ctas array to expandableDetails.ctas
            if (hasCtas) {
              expandableDetails.ctas = templateCtas.map((ctaItem) => ({
                type: ctaItem?.type === URL ? EXTERNAL_URL : ctaItem?.type,
                action: ctaItem?.action || '',
                title: ctaItem?.actionText || ctaItem?.title || '',
                actionLink: ctaItem?.actionLink || '',
              }));
            }
          } else if (templateExpandableDetails) {
            // If expandableDetails already exists, use it
            expandableDetails = {
              media: templateExpandableDetails?.media || [],
              ctas: templateExpandableDetails?.ctas || [],
            };
          }
          
          // Convert from creatives format to campaign format
          templateData = {
            channel,
            messageContent: {
              content: {
                channel: constants.WEBPUSH,
                accountId,
                content: {
                  title: title || '',
                  message: message || '',
                  ...(iconImageUrl && { iconImageUrl }),
                  ...(cta && { cta }),
                  ...(expandableDetails && { expandableDetails }),
                },
                messageSubject: channelTemplate?.name ? channelTemplate.name : 'messageSubject',
                offers: [],
              },
            },
          };
        }
        break;
      }
      default:
        break;
    }
    return templateData;
  };

  getSlideBoxContent({ mode, templateData, isFullMode }) {
    let creativesMode = isFullMode ? 'createTemplate' : 'templates';// for library mode templates page is initial mode and for full mode createTemplates
    if (mode === 'create' && isFullMode) {
      creativesMode = 'createTemplate';
    } else if (mode === 'create' && isEmpty(templateData)) {
      creativesMode = 'templates';
    } else if (mode === 'edit') {
      creativesMode = 'editTemplate';
    } else if (mode === 'preview' && isFullMode) {
      creativesMode = 'preview';
    }
    return creativesMode;
  }

  logGTMEvent(channel, creativesData) {
    const LIBRARY = 'library';
    const timeTaken = GA.timeTracker.stopTimer(CREATIVES_CONTAINER, {
      category: 'Campaigns',
      action: 'Creatives',
      label: 'Indirect',
    });
    const {
      androidContent: {
        title: androidTitle,
        message: androidMessage,
        type: androidType,
      } = {},
      iosContent: {
        title: iosTitle,
        message: iosMessage,
        type: iosType,
      } = {},
      messageBody = '',
      emailBody = '',
    } = creativesData;
    let gtmDetails = {
      channel,
      timeTaken,
      mode: LIBRARY,
      content: messageBody,
    };
    switch (channel) {
      case constants.SMS:
      case constants.WECHAT:
      case constants.VIBER:
      case constants.WEBPUSH:
        break;
      case constants.EMAIL:
        gtmDetails = {
          ...gtmDetails,
          content: emailBody,
        };
        break;
      case constants.MOBILE_PUSH:
      case constants.INAPP:
        gtmDetails = {
          ...gtmDetails,

          content: `${androidTitle} ${androidMessage} ${iosTitle} ${iosMessage}`,
          imageAdded: androidType === 'IMAGE' || iosType === 'IMAGE',
        };
        break;
      case constants.LINE:
        gtmDetails = Object.assign({
          ...gtmDetails,
        }, this.getLineMessageTypes(messageBody));
        break;
      default:
        return false;
    }
    gtmPush('creativeDetails', gtmDetails);
  }

  getLineMessageTypes(messageBody) {
    const {
      messages: lineMessages = [],
    } = JSON.parse(messageBody);
    const typeOfMessages = lineMessages.map((message) => message.type);
    return {
      imageAdded: typeOfMessages.some((type) => [LINE_IMAGE, IMAGE_MAP, IMAGE_CAROUSEL, TEMPLATE].includes(type)),
      videoAdded: typeOfMessages.includes(LINE_VIDEO),
      stickerAdded: typeOfMessages.includes(STICKER),
    };
  }

  getFormData = (template) => {
    // Always reset isGetFormData so the child does not re-send form data on every re-render
    // (e.g. when user fixes validation error by typing, we must not auto-close the slidebox)
    this.setState({ isGetFormData: false });
    if (template.validity) {
      this.setState(
        {},
        () => {
          const templateData = this.state.templateData ? this.state.templateData : template; //select existing or create new content
          const channel = templateData.type;
          const creativesData = this.getCreativesData(channel, template, templateData);// convers data to consumer understandable format
          creativesData.then((data) => {
            this.logGTMEvent(channel, data);
            this.processCentralCommsMetaId(channel, data);
          });
        },
      );
    }
  }

  processCentralCommsMetaId = (channel, creativesData) => {
    // Create the payload for the centralcommnsmetaId API call
    const { isLoyaltyModule = false, loyaltyMetaData = {} } = this.props;
    const { actionName, setMetaData = () => { } } = loyaltyMetaData;

    // const isTemplateModified = getTemplateDiffState(
    //   channel,
    //   loyaltyMetaData,
    //   creativesData
    // );
    if (
      loyaltyMetaData
      && isLoyaltyModule
      // && isTemplateModified
      && actionName === constants.LOYALTY_SUPPORTED_ACTION
    ) {
      const payload = transformChannelPayload(creativesData, {
        channel,
        loyaltyMetaData,
      });

      // Callback function to handle API response
      const handleMetaIDResult = (result) => {
        if (result?.status?.code === 200) {
          setMetaData(result);
          this.props.getCreativesData(creativesData);
        } else {
          CapNotification.error({ message: <FormattedMessage {...messages.somethingWentWrong} /> });
        }
      };

      // Call the action to create central comms meta ID
      this.props.globalActions.createCentralCommsMetaId(payload, handleMetaIDResult);
    } else {
      // If not a loyalty module or different action, should work as usual
      this.props.getCreativesData(creativesData);
    }
  };

  setIsLoadingContent = (isLoadingContent) => {
    if (this.state.isLoadingContent !== isLoadingContent) {
      this.setState({ isLoadingContent });
    }
  }

  resetStep = () => {
    this.setState((prevState) => {
      let newState = {
        templateStep: 1,
      };
      if (prevState.currentChannel.toUpperCase() === constants.EMAIL) {
        newState = { ...newState, emailCreateMode: null };
      }
      if (prevState.currentChannel.toUpperCase() === constants.INAPP) {
        newState = { ...newState, inAppEditorType: null };
      }
      return newState;
    });
  }

  handleCloseSlideBox = () => {
    const { currentChannel = '', slidBoxContent = '' } = this.state;
    const reloadTemplates = currentChannel === constants.WHATSAPP && slidBoxContent === 'editTemplate';
    if (window.location.search.includes('?channel=whatsapp&mode=create')) {
      window.history.pushState({}, null, '/creatives/ui/v2');
    }
    this.setState((prevState) => ({
      ...prevState,
      templateData: undefined,
      showSlideBox: false,
      liquidErrorMessage: { STANDARD_ERROR_MSG: [], LIQUID_ERROR_MSG: [] },
      isLiquidValidationError: false,
    }), () => this.props.handleCloseCreatives(reloadTemplates));
  };

  saveMessage = () => {
    this.setState({ isGetFormData: true });
  };

  discardMessage = () => {
    this.setState({ isDiscardMessage: true });
  }


  // NEW: Handler for Test and Preview button
  handleTestAndPreview = () => {
    this.setState({
      showTestAndPreviewSlidebox: true,
      isTestAndPreviewMode: true, // Set flag to prevent validation
    });
  }

  // NEW: Handler to close Test and Preview slidebox
  handleCloseTestAndPreview = () => {
    this.setState({
      showTestAndPreviewSlidebox: false,
      isTestAndPreviewMode: false, // Reset flag when closing
    });
  }

  shouldShowFooter = () => {
    const { isFullMode } = this.props;
    const {
      slidBoxContent, currentChannel, emailCreateMode, templateNameExists, templateStep, mobilePushCreateMode, weChatTemplateType, templateData, inAppCreateMode,
    } = this.state;
    const channel = currentChannel.toUpperCase();
    const currentStep = this.creativesTemplateSteps[templateStep];
    let showFooter = false;
    showFooter = isFullMode && slidBoxContent === "preview";
    const isMobilepush = channel === constants.MOBILE_PUSH;

    const supportCKEditor = commonUtil.hasSupportCKEditor();
    if (!supportCKEditor && channel === constants.EMAIL && currentStep === 'modeSelection' && slidBoxContent === 'createTemplate') {
      return true;
    }
    if (!supportCKEditor && channel === constants.EMAIL && currentStep === 'createTemplateContent' && slidBoxContent === 'createTemplate') {
      showFooter = true;
    }

    if (!isFullMode) {
      const isEmailCreate = slidBoxContent === 'createTemplate' && channel === constants.EMAIL && currentStep !== 'createTemplateContent';
      const isCreate = (slidBoxContent === 'editTemplate' || slidBoxContent === 'createTemplate') && !isEmailCreate;
      const isCallTask = channel === constants.CALL_TASK;
      showFooter = (isCreate || (isEmailCreate && emailCreateMode) || slidBoxContent === 'preview') && !isCallTask;
      if (isMobilepush) {
        showFooter = currentStep === "modeSelection" || (currentStep === 'createTemplateContent' && !isEmpty(mobilePushCreateMode));
      }
    } else if (channel === constants.EMAIL && isFullMode) {
      const isEmailCreate = slidBoxContent === 'createTemplate' && channel === constants.EMAIL && currentStep !== 'createTemplateContent';
      // CK editor flow: show footer on mode selection when a card is selected so user sees Continue (disabled until name + card)
      if (supportCKEditor && slidBoxContent === 'createTemplate' && currentStep === 'modeSelection') {
        showFooter = !!emailCreateMode;
      } else {
        showFooter = isEmailCreate && emailCreateMode && templateNameExists;
      }
    }
    if (channel === constants.EMAIL && emailCreateMode === "upload") {
      showFooter = showFooter && !this.props.isUploading;
    }
    if (slidBoxContent === 'createTemplate' && channel === constants.EMAIL && emailCreateMode && currentStep === 'createTemplateContent') { // full mode create flow email
      showFooter = true;
    }
    if (slidBoxContent === "editTemplate" && ((channel === constants.EMAIL && currentStep === 'modeSelection'))) {
      showFooter = true;
    }
    if (channel === constants.MOBILE_PUSH
      && ((slidBoxContent === 'createTemplate' && !isEmpty(mobilePushCreateMode))
        || (slidBoxContent === 'editTemplate' && (currentStep === 'modeSelection' || isFullMode)))
      && templateNameExists) {
      showFooter = true;
    }

    if (channel === constants.WECHAT
      && ((slidBoxContent === 'createTemplate' && !isEmpty(weChatTemplateType))
        || (slidBoxContent === 'editTemplate' && currentStep === 'modeSelection'))) {
      showFooter = true;
    }


    if (showFooter) {
      if (slidBoxContent === "createTemplate" && ((channel === constants.EMAIL && currentStep === 'createTemplateContent')
        || ([constants.SMS, constants.WECHAT].includes(channel) && currentStep === 'modeSelection'))) {
        showFooter = showFooter && !this.state.isLoadingContent;
      } else if (slidBoxContent === "editTemplate"
        && ([constants.SMS, constants.WECHAT, constants.EMAIL].includes(channel)
          && currentStep === 'modeSelection')) {
        showFooter = showFooter && !this.state.isLoadingContent;
      }
    }

    const isLineViberChannel = templateData && [constants.LINE, constants.VIBER].includes(templateData);
    if ([constants.LINE, constants.VIBER, constants.FACEBOOK].includes(channel) || isLineViberChannel) {
      showFooter = false;
    }


    return showFooter;
  }

  shouldShowDoneFooter = () => {
    const {
      slidBoxContent, templateStep, currentChannel, templateData, inAppCreateMode,
    } = this.state;
    const { isFullMode } = this.props;
    const currentStep = this.creativesTemplateSteps[templateStep];
    let showDone = false;
    const channelName = !isFullMode && templateData ? templateData.type : currentChannel;
    const channel = channelName?.toUpperCase();

    // Check supportCKEditor flag for new HTML editor flow
    const supportCKEditor = commonUtil.hasSupportCKEditor();
    if (channel === constants.EMAIL || channel === constants.SMS) {
      const isEmailCreate = slidBoxContent === 'createTemplate' && channel === constants.EMAIL && currentStep !== 'createTemplateContent';

      // For new HTML editor flow (when supportCKEditor is false), show Done footer when in createTemplateContent step
      if (!supportCKEditor && channel === constants.EMAIL && slidBoxContent === 'createTemplate' && currentStep === 'createTemplateContent') {
        showDone = true;
      } else {
        showDone = (slidBoxContent === 'editTemplate' || slidBoxContent === 'createTemplate') && !isEmailCreate;
      }
    } else if ([constants.WECHAT, constants.MOBILE_PUSH].includes(channel)) {
      showDone = currentStep === "createTemplateContent" || slidBoxContent === "editTemplate";

      // Additional condition for MobilePush edit in full mode
      if (channel === constants.MOBILE_PUSH && slidBoxContent === "editTemplate" && isFullMode) {
        showDone = true;
      }
    }

    return showDone;
  }

  templateNameComponentHeader = ({ formData, onFormDataChange, name }) => (
    <CapHeader
      inline
      title={name}
      className="support-video-elements"
      description={(
        <CapLink
          title={<FormattedMessage {...messages.creativesTemplatesEditName} />}
          onClick={() => { this.setState({ isEditName: true }, () => { this.showTemplateName({ formData, onFormDataChange }); }); }} />
      )
      } />
  )

  templateNameComponentInput = ({ formData, onFormDataChange, name }) => (
    <TemplateNameInputField
      initialValue={name}
      suffix={<span />}
      onBlur={(committedValue) => {
        this.performTemplateNameUpdate(committedValue, formData, onFormDataChange);
        this.setState({ isEditName: false });
      }}
      onChange={(value) => {
        const isEmptyTemplateName = !value.trim();
        if (this.state.isTemplateNameEmpty !== isEmptyTemplateName) {
          this.setState({ isTemplateNameEmpty: isEmptyTemplateName });
        }
      }}
    />
  )

  showTemplateName = ({ formData, onFormDataChange }) => { //gets called from email/index after template data is fetched
    const {
      slidBoxContent, currentChannel, isEditName, templateStep,
    } = this.state;
    const channel = currentChannel.toUpperCase();
    if ([constants.EMAIL, constants.MOBILE_PUSH, constants.INAPP].includes(channel) && (slidBoxContent === 'editTemplate' || slidBoxContent === 'createTemplate')) {
      const name = get(formData, 'template-name');

      const isModeSelectionStep = templateStep === 'modeSelection' || this.creativesTemplateSteps[templateStep] === 'modeSelection';
      const isCreateMode = slidBoxContent === 'createTemplate';
      if (isCreateMode && isModeSelectionStep) {
        return;
      }
      if (channel === constants.EMAIL && !name && slidBoxContent === 'createTemplate') {
        this.setState({ isTemplateNameEmpty: true });
      }
      this.templateContainerDetails = { formData, onFormDataChange };
      if (name && !isEditName) {
        this.setState({ showTemplateNameComponentEdit: false });
      } else if (isEditName) {
        this.setState({
          showTemplateNameComponentEdit: true,
          localTemplateName: name || '', // Initialize local state with current value
        });
      }
    }
  }

  showLiquidErrorInFooter = (errorMessagesFromFormBuilder, currentFormBuilderTab) => {
    const liquidMsgs = get(errorMessagesFromFormBuilder, constants.LIQUID_ERROR_MSG, []);
    const standardMsgs = get(errorMessagesFromFormBuilder, constants.STANDARD_ERROR_MSG, []);
    const hasLiquid = !isDeepEmpty(liquidMsgs);
    const hasStandard = !isDeepEmpty(standardMsgs);
    const isLiquidValidationError = hasLiquid || hasStandard;
    // Don't overwrite existing liquid error with empty only for Mobile Push OLD (FormBuilder/clear calls empty there); SMS/others clear on input change
    const isMobilePush = this.state.currentChannel?.toUpperCase() === constants.MOBILE_PUSH;
    if (!hasLiquid && !hasStandard && this.state.isLiquidValidationError && isMobilePush) {
      return;
    }
    this.setState({
      isLiquidValidationError,
      liquidErrorMessage: errorMessagesFromFormBuilder,
      activeFormBuilderTab: currentFormBuilderTab === 1 ? constants.ANDROID : (currentFormBuilderTab === 2 ? constants.IOS : null), // Update activeFormBuilderTab, default to 1 if undefined
    });
  }

  // Callback to update HTML Editor validation state (called from EmailWrapper)
  updateHtmlEditorValidationState = (validationState) => {
    this.setState({
      htmlEditorValidationState: validationState,
    });
  }

  handlePersonalizationTokensChange = (hasTokens) => {
    this.setState({
      hasPersonalizationTokenError: hasTokens,
    });
  }

  shouldShowContinueFooter = () => { // only for email for now, has to be modified according to channel
    const {
      slidBoxContent, templateStep, currentChannel, emailCreateMode, mobilePushCreateMode, inAppEditorType, weChatTemplateType,
    } = this.state;
    const { isFullMode } = this.props;
    const channel = currentChannel?.toUpperCase?.() || '';
    // In library/embedded mode show Continue only for EMAIL and MOBILE_PUSH; hide for other channels
    if (!isFullMode && channel !== constants.EMAIL && channel !== constants.MOBILE_PUSH) {
      return false;
    }
    let isShowContinueFooter = false;
    const currentStep = this.creativesTemplateSteps[templateStep];
    // Check if supportCKEditor is false (new flow)
    const supportCKEditor = commonUtil.hasSupportCKEditor(); // Default to legacy flow
    if (channel === constants.EMAIL || channel === constants.SMS) {
      // New flow: Show Continue button when supportCKEditor is false and in modeSelection (full mode only)
      if (!supportCKEditor && currentStep === 'modeSelection' && slidBoxContent === 'createTemplate') {
        return true;
      }

      // Legacy flow: Original logic (only when supportCKEditor is true)
      if (supportCKEditor && ((emailCreateMode === "upload" && !isEmpty(this.props.EmailLayout)) || emailCreateMode === "editor")) {
        let isEmailCreate = slidBoxContent === 'createTemplate';
        isEmailCreate = currentChannel.toUpperCase() === constants.EMAIL && ((emailCreateMode === "upload" && currentStep !== 'createTemplateContent') || (emailCreateMode === "editor" && currentStep !== 'createTemplateContent' && currentStep !== "templateSelection"));
        isShowContinueFooter = isEmailCreate && emailCreateMode;
      }
    } else if (channel === constants.MOBILE_PUSH) {
      isShowContinueFooter = !isEmpty(mobilePushCreateMode) && currentStep === "modeSelection";
    } else if (channel === constants.WECHAT) {
      isShowContinueFooter = !isEmpty(weChatTemplateType) && currentStep === "modeSelection";
    }

    return isShowContinueFooter;
  }

  templateNameRenderProp = () => {
    const { showTemplateNameComponentEdit, currentChannel, slidBoxContent } = this.state;
    const { templateContainerDetails } = this;
    const { formData, onFormDataChange } = templateContainerDetails;
    const channel = currentChannel.toUpperCase();
    if ([constants.EMAIL, constants.MOBILE_PUSH, constants.INAPP].includes(channel) && (slidBoxContent === 'editTemplate' || slidBoxContent === 'createTemplate')) {
      const name = get(formData, 'template-name');
      return showTemplateNameComponentEdit ? this.templateNameComponentInput({ formData, onFormDataChange, name }) : this.templateNameComponentHeader({ formData, onFormDataChange, name });
    }
    return false;
  }

  shouldShowHeader = () => {
    const { currentChannel, slidBoxContent } = this.state;
    if (currentChannel.toUpperCase() === constants.FACEBOOK && slidBoxContent === 'createTemplate') {
      return false;
    }
    return true;
  }

  // Check if Continue button should be disabled (for new flow only)
  isContinueButtonDisabled = () => {
    const {
      currentChannel, emailCreateMode, templateNameExists, mobilePushCreateMode, templateStep,
    } = this.state;
    const { isFullMode, EmailLayout } = this.props;
    if (currentChannel.toUpperCase() === constants.EMAIL) {
      // Upload mode: enable when a file has been uploaded (EmailLayout set by ZIP or HTML upload)
      // Other modes: enable when an editor type is selected (html_editor, drag_drop, editor)
      const isUploadComplete = emailCreateMode === 'upload' && !isEmpty(EmailLayout);
      const isEditorSelected = !!emailCreateMode && emailCreateMode !== 'upload';
      const canContinue = isUploadComplete || isEditorSelected;
      // In full mode: require both template name AND (upload complete or editor selected)
      // In library mode: require only upload complete or editor selection
      // Same rules for both CK editor and non-CK flows
      if (isFullMode) {
        const isTemplateNameValid = templateNameExists;
        return !(isTemplateNameValid && canContinue);
      }
      return !canContinue;
    }
    if (currentChannel.toUpperCase() === constants.MOBILE_PUSH) {
      const currentStep = this.creativesTemplateSteps[templateStep];
      return !(!isEmpty(mobilePushCreateMode) && currentStep === 'modeSelection');
    }
    return false;
  }

  render() {
    const {
      slidBoxContent,
      isGetFormData,
      showSlideBox,
      templateData,
      currentChannel,
      emailCreateMode,
      selectedEmailCreateMode,
      templateStep,
      isLoadingContent,
      mobilePushCreateMode,
      isDiscardMessage,
      weChatTemplateType,
      weChatMaptemplateStep,
      isTemplateNameEmpty,
      isLiquidValidationError,
      liquidErrorMessage,
      activeFormBuilderTab,
      showTestAndPreviewSlidebox,
      isTestAndPreviewMode,
      inAppEditorType,
      htmlEditorValidationState,
    } = this.state;
    const {
      isFullMode,
      creativesMode,
      cap,
      isUploading,
      channelsToHide,
      selectedWeChatAccount,
      forwardedTags,
      channelsToDisable,
      selectedOfferDetails,
      onTestContentClicked,
      onPreviewContentClicked,
      getCreativesData,
      fetchingCmsData,
      editor,
      smsRegister,
      enableNewChannels,
      eventContextTags,
      waitEventContextTags = {},
      isLoyaltyModule,
      loyaltyMetaData = {},
    } = this.props;
    // Compute Continue button label: "Continue" for EMAIL (when CK) and MOBILE_PUSH; "Next" for others
    const supportCKEditor = commonUtil.hasSupportCKEditor();
    const useContinueLabel = (currentChannel?.toUpperCase() === constants.EMAIL && supportCKEditor)
      || currentChannel?.toUpperCase() === constants.MOBILE_PUSH;
    const continueButtonLabel = useContinueLabel ? messages.continue : messages.next;

    const mapTemplateCreate = slidBoxContent === "createTemplate"
      && weChatTemplateType === MAP_TEMPLATE
      && templateStep !== "modeSelection";

    // Determine if we're in HTML Editor mode (where errors are shown in ValidationErrorDisplay, not ErrorInfoNote in footer)
    const isEmailChannel = currentChannel?.toUpperCase() === constants.EMAIL;
    const isEditMode = slidBoxContent === 'editTemplate';
    const isHTMLEditorModeInCreate = selectedEmailCreateMode === 'html_editor';
    const isHTMLEditorModeInEdit = isEditMode && htmlEditorValidationState != null;
    const isHTMLEditorMode = isEmailChannel && (isHTMLEditorModeInCreate || isHTMLEditorModeInEdit);
    const isBEEEditor = selectedEmailCreateMode === 'drag_drop'
      || (emailCreateMode === 'editor' && !isHTMLEditorMode);

    // Check for BEE editor errors (same logic as SlideBoxFooter)
    const hasStandardErrors = liquidErrorMessage && liquidErrorMessage.STANDARD_ERROR_MSG && liquidErrorMessage.STANDARD_ERROR_MSG.length > 0;
    const hasLiquidErrors = liquidErrorMessage && liquidErrorMessage.LIQUID_ERROR_MSG && liquidErrorMessage.LIQUID_ERROR_MSG.length > 0;
    const htmlEditorHasErrors = htmlEditorValidationState && htmlEditorValidationState.issueCounts && htmlEditorValidationState.issueCounts.total > 0;
    const hasBEEEditorErrors = isEmailChannel && (hasStandardErrors || hasLiquidErrors) && (!htmlEditorValidationState || !htmlEditorHasErrors);

    // Only apply margin to footer when ErrorInfoNote is shown in footer (BEE editor)
    // For HTML Editor, errors are shown in ValidationErrorDisplay (inside content area), so no footer margin needed
    // IMPORTANT: Never show ErrorInfoNote in footer when in HTML Editor mode, even if liquidErrorMessage exists
    const shouldShowErrorInfoNoteInFooter = isHTMLEditorMode ? false : hasBEEEditorErrors;

    // Calculate margin for header/content (always apply if there are errors, regardless of editor type)
    const slideBoxWrapperMargin = (get(liquidErrorMessage, 'STANDARD_ERROR_MSG.length', 0) > 0 && get(liquidErrorMessage, 'LIQUID_ERROR_MSG.length', 0) > 0)
      ? CAP_SPACE_64
      : get(liquidErrorMessage, 'LIQUID_ERROR_MSG.length', 0) > 0
        ? CAP_SPACE_56
        : get(liquidErrorMessage, 'STANDARD_ERROR_MSG.length', 0) > 0
          ? CAP_SPACE_32
          : 0;
    /* TODO: Instead of passing down same props separately to each component down, write common function to these props and pass it accordingly */

    // Compute anonymous user type and channel restrictions
    const { customerType = '' } = this.props;
    const isAnonymousType = [constants.VISITOR, constants.MIXED].includes(customerType);
    const restrictPersonalization = isAnonymousType;

    // For anonymous users, only MOBILEPUSH and WEBPUSH channels are allowed
    let updatedChannelsToHide = [...(channelsToHide || [])];
    if (isAnonymousType) {
      const allowedChannels = constants.ALLOWED_CHANNELS_FOR_ANONYMOUS;
      const allChannels = constants.ALL_CHANNELS_NEW;
      const channelsToRemove = allChannels.filter((channel) => !allowedChannels.includes(channel));
      updatedChannelsToHide = [...new Set([...updatedChannelsToHide, ...channelsToRemove])];
    }
    // In library mode (journey module), hide mobilepush and wechat channels from engagement blocks
    // unless the current engagement block itself is that channel (e.g. mobilepush block should show mobilepush tab)
    const isJourneyModule = (this.props.messageDetails?.type || '').toLowerCase() === constants.JOURNEY;
    if (!isFullMode && isJourneyModule) {
      const currentChannelNorm = (currentChannel || '').toLowerCase();
      const journeyChannelsToHide = ['mobilepush', 'wechat'].filter((ch) => ch !== currentChannelNorm);
      updatedChannelsToHide = [...new Set([...updatedChannelsToHide, ...journeyChannelsToHide])];
    }

    return (
      <SlideBoxWrapper
        slideBoxWrapperMargin={slideBoxWrapperMargin}
        shouldApplyFooterMargin={shouldShowErrorInfoNoteInFooter}
        className={classnames(`${classPrefix} ${isFullMode ? 'creatives-full-mode' : 'creatives-library-mode'} ${mapTemplateCreate ? 'map-template-create' : ''}`)}
      >
        <CapSlideBox
          header={
            this.shouldShowHeader() && (
              <SlideBoxHeader
                key="creatives-container-slidebox-header"
                channel={currentChannel}
                messages={this.props.messages}
                slidBoxContent={this.state.slidBoxContent}
                templateData={templateData}
                onShowTemplates={this.onShowTemplates}
                creativesMode={creativesMode}
                isFullMode={isFullMode}
                isLoadingContent={isLoadingContent}
                shouldShowTemplateName={this.templateContainerDetails}
                templateNameRenderProp={this.templateNameRenderProp}
                weChatMaptemplateStep={weChatMaptemplateStep}
                onWeChatMaptemplateStepChange={this.onWeChatMaptemplateStepChange}
                weChatTemplateType={weChatTemplateType}
                showPrefix={!isUploading} // not show back button when email template is being uploaded
                templateStep={this.creativesTemplateSteps[templateStep]}
                smsRegister={smsRegister}
                handleClose={this.handleCloseSlideBox}
                moduleType={this.props.messageDetails?.type}
              />
            )}
          content={(
            <SlideBoxContent
              key="creatives-container-slidebox-content"
              onSelectTemplate={this.onSelectTemplate}
              onCreateComplete={getCreativesData}
              onPreviewTemplate={this.onPreviewTemplate}
              slidBoxContent={slidBoxContent}
              templateData={templateData}
              campaignSettings={this.props.Templates.campaignSettings}
              location={this.props.location}
              messageDetails={this.props.messageDetails}
              showDisabledFBInfo={this.props.showDisabledFBInfo}
              getFormData={this.getFormData}
              getLiquidTags={this.props?.globalActions?.getLiquidTags}
              onCallTaskSubmit={this.onCallTaskSubmit}
              onCreateNew={this.onCreateNew}
              isGetFormData={isGetFormData}
              isDiscardMessage={isDiscardMessage}
              isFullMode={isFullMode}
              currentChannel={currentChannel.toUpperCase()}
              onChannelChange={this.onChannelChange}
              onEmailModeChange={this.onEmailModeChange}//used when create is clicked in email
              emailCreateMode={emailCreateMode}// upload zip || use editor are values
              onInAppEditorTypeChange={this.onInAppEditorTypeChange}//used when create is clicked in inapp
              inAppEditorType={inAppEditorType}// htmlEditor || dragDropEditor are values
              templateStep={this.creativesTemplateSteps[templateStep]}
              onCreateNextStep={this.onCreateNextStep}
              onEnterTemplateName={this.onEnterTemplateName}
              onRemoveTemplateName={this.onRemoveTemplateName}
              onResetStep={this.resetStep}
              fbAdManager={this.state.fbAdManager}
              cap={cap}
              setIsLoadingContent={this.setIsLoadingContent}
              onMobilepushModeChange={this.onMobilepushModeChange}
              inAppCreateMode={this.state.inAppCreateMode}
              onInAppModeChange={this.onInAppModeChange}
              mobilePushCreateMode={mobilePushCreateMode}
              showTemplateName={this.showTemplateName}
              onValidationFail={this.onValidationFail}
              channelsToHide={updatedChannelsToHide}
              forwardedTags={forwardedTags}
              selectedOfferDetails={selectedOfferDetails}
              channelsToDisable={channelsToDisable}
              restrictPersonalization={restrictPersonalization}
              isAnonymousType={isAnonymousType}
              customerType={customerType}
              weChatTemplateType={weChatTemplateType}
              onWechatTemplateChange={this.onWechatTemplateChange}
              weChatMaptemplateStep={weChatMaptemplateStep}
              selectedWeChatAccount={selectedWeChatAccount}
              onWeChatMaptemplateStepChange={this.onWeChatMaptemplateStepChange}
              onPreviewContentClicked={onPreviewContentClicked}
              onTestContentClicked={onTestContentClicked}
              onFacebookSubmit={getCreativesData}
              saveMessage={this.saveMessage}
              selectedAccount={this.props.selectedAccount}
              onShowTemplates={this.onShowTemplates}
              handleClose={this.handleCloseSlideBox}
              onFTPSubmit={getCreativesData}
              editor={editor}
              smsRegister={smsRegister}
              messageStrategy={this.props.strategy}
              orgUnitId={this.props.orgUnitId}
              enableNewChannels={enableNewChannels}
              hideTestAndPreviewBtn={this.props.hideTestAndPreviewBtn}
              getCmsTemplatesInProgress={this.props.Templates?.getCmsTemplatesInProgress}
              moduleType={this.props.messageDetails?.type}
              showLiquidErrorInFooter={this.showLiquidErrorInFooter}
              creativesMode={creativesMode} // An existing prop that we're using here. Required to ensure correct account details in Edit or Preview in case of Embedded mode.
              hostName={this.props?.hostName || ''}
              eventContextTags={eventContextTags}
              waitEventContextTags={waitEventContextTags}
              isLoyaltyModule={isLoyaltyModule}
              loyaltyMetaData={loyaltyMetaData}
              showTestAndPreviewSlidebox={showTestAndPreviewSlidebox}
              handleTestAndPreview={this.handleTestAndPreview}
              handleCloseTestAndPreview={this.handleCloseTestAndPreview}
              isTestAndPreviewMode={(() => this.state.isTestAndPreviewMode)()}
              onHtmlEditorValidationStateChange={this.updateHtmlEditorValidationState}
              onPersonalizationTokensChange={this.handlePersonalizationTokensChange}
            />
          )}
          footer={this.shouldShowFooter() ? (
            <SlideBoxFooter
              isFullMode={isFullMode}
              messages={this.props.messages}
              onSave={this.saveMessage}
              onDiscard={this.discardMessage}
              onEditTemplate={this.onEditTemplate}
              isTemplateArchived={!!(commonUtil.hasCreativesArchivalEnabled() && this.props.templateData && this.props.templateData.isArchived)}
              slidBoxContent={slidBoxContent}
              onCreateNextStep={this.onCreateNextStep}
              currentChannel={currentChannel.toUpperCase()}
              templateStep={this.creativesTemplateSteps[templateStep]}
              emailCreateMode={emailCreateMode}
              selectedEmailCreateMode={selectedEmailCreateMode}
              shouldShowContinueFooter={this.shouldShowContinueFooter}
              shouldShowDoneFooter={this.shouldShowDoneFooter}
              fetchingCmsData={fetchingCmsData}
              isTemplateNameEmpty={isTemplateNameEmpty}
              isLiquidValidationError={isLiquidValidationError}
              errorMessages={liquidErrorMessage}
              currentTab={activeFormBuilderTab}
              onTestAndPreview={this.handleTestAndPreview}
              isContinueButtonDisabled={this.isContinueButtonDisabled()}
              continueButtonLabel={continueButtonLabel}
              showTestAndPreviewButton={(() => {
                const isEmailOrSmsOrWhatsappOrRcsOrInAppOrMobilePush = [constants.EMAIL, constants.SMS, constants.WHATSAPP, constants.RCS, constants.INAPP, constants.MOBILE_PUSH, constants.VIBER, constants.ZALO].includes(currentChannel.toUpperCase());
                const showButton = isEmailOrSmsOrWhatsappOrRcsOrInAppOrMobilePush && (slidBoxContent === 'editTemplate' || slidBoxContent === 'createTemplate');
                return showButton;
              })()}
              htmlEditorValidationState={htmlEditorValidationState}
              isCreatingTemplate={slidBoxContent === 'createTemplate' && currentChannel.toUpperCase() === constants.EMAIL}
              restrictPersonalization={restrictPersonalization}
              isAnonymousType={isAnonymousType}
              templateData={templateData}
              hasPersonalizationTokenError={this.state.hasPersonalizationTokenError}
            />
          ) : isLiquidValidationError && (
            <CapRow className="template-footer-width">
              {(() => {
                const errorsToShow = get(liquidErrorMessage, constants.LIQUID_ERROR_MSG, []);
                const standardErrorsToShow = get(liquidErrorMessage, constants.STANDARD_ERROR_MSG, []);
                return <ErrorInfoNote currentTab={activeFormBuilderTab?.toUpperCase()} errorMessages={{ LIQUID_ERROR_MSG: errorsToShow, STANDARD_ERROR_MSG: standardErrorsToShow }} />;
              })()}
            </CapRow>
          )}
          handleClose={this.handleCloseSlideBox}
          show={showSlideBox}
          size="size-xl"
        />
      </SlideBoxWrapper>
    );
  }
}

Creatives.propTypes = {
  getCreativesData: PropTypes.func,
  messages: PropTypes.object,
  messageDetails: PropTypes.object,
  creativesMode: PropTypes.string,
  location: PropTypes.object,
  handleCloseCreatives: PropTypes.func,
  templateData: PropTypes.object,
  isFullMode: PropTypes.bool,
  channel: PropTypes.string,
  templateActions: PropTypes.object,
  globalActions: PropTypes.object,
  zaloActions: PropTypes.object,
  cap: PropTypes.object,
  // isLoading: PropTypes.bool,
  templateUserList: PropTypes.array,
  isUploading: PropTypes.bool,
  EmailLayout: PropTypes.string,
  channelsToHide: PropTypes.array,
  forwardedTags: PropTypes.object,
  selectedOfferDetails: PropTypes.array,
  channelsToDisable: PropTypes.array,
  selectedWeChatAccount: PropTypes.object,
  Templates: PropTypes.object,
  selectedAccount: PropTypes.object,
  strategy: PropTypes.string,
  orgUnitId: PropTypes.number,
  hostName: PropTypes.string,
  eventContextTags: PropTypes.array,
  waitEventContextTags: PropTypes.object,
  loyaltyTagFetchingDependencies: PropTypes.object,
  customerType: PropTypes.string,
  intl: PropTypes.shape({
    formatMessage: PropTypes.func,
  }),
  stopValidation: PropTypes.func,
};
const mapStatesToProps = () => createStructuredSelector({
  isLoading: isLoadingSelector(),
  templateUserList: templateUserList(),
  EmailLayout: selectEmailLayout(),
  isUploading: uploadSelector(),
  Templates: makeSelectTemplates(),
  fetchingCmsData: makeSelectFetchingCmsData(),
});
function mapDispatchToProps(dispatch) {
  return {
    templateActions: bindActionCreators(templateActions, dispatch),
    globalActions: bindActionCreators(globalActions, dispatch),
    actions: bindActionCreators(actions, dispatch),
    zaloActions: bindActionCreators(zaloActions, dispatch),
  };
}

const withConnect = connect(mapStatesToProps, mapDispatchToProps);
const withReducer = injectReducer({ key: 'creativesContainer', reducer: creativesContainerReducer });
const withSaga = injectSaga({ key: 'cap', saga: capSagaForFetchSchemaForEntity });
const withLiquidSaga = injectSaga({ key: 'liquid', saga: capSagaLiquidEntity, mode: DAEMON });
const withDefaultTempSaga = injectSaga({ key: 'creativesContainer', saga: v2TemplateSagaWatchGetDefaultBeeTemplates });

export default compose(withSaga, withLiquidSaga, withDefaultTempSaga, withReducer, withConnect)(injectIntl(Creatives));
