/*
 *
 * TemplatesV2
 *
 */

import PropTypes from 'prop-types';
import React from 'react';
import { connect } from 'react-redux';
import { injectIntl, intlShape, FormattedMessage } from 'react-intl';
import { createStructuredSelector } from 'reselect';
import { bindActionCreators, compose } from 'redux';
import { CapTab, CapCustomCard, CapButton, CapHeader, CapSpin, CapIcon, CapTooltip } from '@capillarytech/cap-ui-library';
import { find, get } from 'lodash';
import Helmet from 'react-helmet';

import { UserIsAuthenticated } from '../../utils/authWrapper';
import { makeSelectTemplates, makeSelectTemplatesResponse } from '../Templates/selectors';
import messages from './messages';
import * as actions from './actions';
import * as templateActions from '../Templates/actions';
import Templates from '../Templates';
import * as commonUtil from '../../utils/common';
import CallTask from '../CallTask';
import Facebook from '../Facebook';
import Viber from '../Viber';
import Line from '../Line/Container';
import FTP from '../FTP';
import Gallery from '../Assets/Gallery';
import withStyles from '../../hoc/withStyles';
import styles, { CapTabStyle } from './TemplatesV2.style';
import { CREATIVES_UI_VIEW, FTP as FTP_CHANNEL, LOYALTY, WHATSAPP, RCS, LINE, EMAIL, ASSETS, JP_LOCALE_HIDE_FEATURE, ZALO, INAPP, WEBPUSH } from '../App/constants';
import AccessForbidden from '../../v2Components/AccessForbidden';
import { getObjFromQueryParams } from '../../utils/v2common';
import { makeSelectAuthenticated, selectCurrentOrgDetails } from "../../v2Containers/Cap/selectors";
import {
  CALL_TASK,
  COMMON_CHANNELS,
  LOYALTY_SUPPORTED_ACTION,
  MOBILE_PUSH,
  NORMALIZED_CHANNEL_ALIASES,
  SMS,
} from "../CreativesContainer/constants";

const {CapCustomCardList} = CapCustomCard;

const StyledCapTab = withStyles(CapTab, CapTabStyle);
export class TemplatesV2 extends React.Component { // eslint-disable-line react/prefer-stateless-function
  constructor(props) {
    super(props);
    let defaultChannel = get(this, 'props.channel') || get(this, 'props.params.channel') || 'sms';
    if (defaultChannel === LOYALTY) {
      defaultChannel = 'sms';
    }
    const {
      intl,
      channelsToHide = [],
      channelsToDisable = [],
      isFullMode,
      onChannelChange,
      showDisabledFBInfo,
      enableNewChannels = [],
      currentOrgDetails = {},
      cap = {},
      loyaltyMetaData = {},
      isLoyaltyModule = false,
      isAnonymousType = false,
    } = props;

    const defaultPanes = {
      sms: {content: <></>, tab: intl.formatMessage(messages.sms), key: 'sms'},
      email: {content: <></>, tab: intl.formatMessage(messages.email), key: 'email'},
      //'wechat': {content: this.getTemplatesComponent('wechat'), tab: 'Wechat', key: 'wechat'},
      mPush: {content: <></>, tab: intl.formatMessage(messages.pushNotification), key: 'mobilepush'},
      ...(commonUtil.hasWebPushFeatureEnabled() ? {
        webpush: {
          content: <div></div>,
          tab: intl.formatMessage(messages.webPush),
          key: WEBPUSH,
        }
      } : {}),
      viber: {content: <></>, tab: intl.formatMessage(messages.viber), key: 'viber'},
      whatsapp: { content: <></>, tab: intl.formatMessage(messages.whatsapp), key: WHATSAPP },
      zalo: { content: <div></div>, tab: intl.formatMessage(messages.zalo), key: ZALO },
      facebook: {content: <div></div>, tab: intl.formatMessage(messages.facebook), key: 'facebook'},
      rcs: { content: <></>, tab: intl.formatMessage(messages.rcs), key: RCS },
      inApp: { content: <div></div>, tab: intl.formatMessage(messages.inapp), key: INAPP },
      line: {content: <></>, tab: intl.formatMessage(messages.line), key: 'line'},
    };
    //Hiding we chat for all orgs across UI for now and enabling it based on feature 'ENABLE_WECHAT'

    if (commonUtil.hasWechatFeatureEnabled()) {
      defaultPanes.weChat = {
        content: <></>,
        tab: intl.formatMessage(messages.wechat),
        key: 'wechat',
      };
    }
    // Robust normalization function: converts camelCase, hyphens, spaces and mixed-case to snake_case lowercase
    const normalizeChannel = (raw = '') => {
      const str = (raw || '').toString();
      return str.replace(/([a-z0-9])([A-Z])/g, '$1_$2').replace(/[^a-zA-Z0-9]+/g, '_').toLowerCase();
    };

    const buildChannelSet = (channelList) => {
      const normalized = (channelList || []).map((c) => normalizeChannel(c));
      const withAliases = normalized.flatMap((norm) => {
        const canonical = NORMALIZED_CHANNEL_ALIASES[norm];
        return canonical ? [norm, canonical] : [norm];
      });
      return new Set(withAliases);
    };
    const normalizedChannelsToHideSet = buildChannelSet(channelsToHide);
    const normalizedChannelsToDisableSet = buildChannelSet(channelsToDisable);

    // Build filtered panes by examining each pane's `key` and checking against normalized hide set
    let filteredPanes = Object.keys(defaultPanes).map((k) => defaultPanes[k]).filter((pane) => {
      const paneKey = normalizeChannel(pane.key);
      return !normalizedChannelsToHideSet.has(paneKey);
    });

    if (isFullMode) {
      filteredPanes.push({ content: <div></div>, tab: intl.formatMessage(messages.gallery), key: 'assets' });
    } else {
      // Add special-mode panes only when not hidden (use normalized checks)
      if (!normalizedChannelsToHideSet.has(CALL_TASK.toLowerCase())) {
        filteredPanes.push({ content: <div></div>, tab: intl.formatMessage(messages.callTask), key: CALL_TASK.toLowerCase() });
      }
      if (!normalizedChannelsToHideSet.has(FTP_CHANNEL.toLowerCase())) {
        filteredPanes.push({ content: <></>, tab: intl.formatMessage(messages.FTP), key: FTP_CHANNEL.toLowerCase() });
        defaultChannel = FTP_CHANNEL;
      }

      // Create a local copy of COMMON_CHANNELS to avoid mutating the imported array
      const channels = [...COMMON_CHANNELS];
      const { actionName = '' } = loyaltyMetaData;
      if (isLoyaltyModule && actionName === LOYALTY_SUPPORTED_ACTION) {
        channels.push(WHATSAPP, ZALO);
      }

      // we only show channels other than COMMON_CHANNELS if they are present in enableNewChannels
      filteredPanes = filteredPanes.filter((item) => {
        const channelKey = normalizeChannel(item.key);
        if (!channels.includes(channelKey)) {
          return enableNewChannels.includes(channelKey.toUpperCase());
        }
        return true;
      });
    }


    filteredPanes = filteredPanes.map((pane) => {
      const paneKeyNorm = normalizeChannel(pane.key);
      if (normalizedChannelsToDisableSet.has(paneKeyNorm)) {
        // eslint-disable-next-line no-param-reassign
        pane.disabled = true;
        if (pane.key === 'facebook' && showDisabledFBInfo) {
          pane.tab = (<CapTooltip
            title={
            intl.formatMessage(messages.facebookDisableinfo)
          }
        >
            {intl.formatMessage(messages.facebook)}
          </CapTooltip>);
        }
      }
      return pane;
    });

    // This data will be available when it will be accessed in full mode
    const { accessibleFeatures = [] } = currentOrgDetails || {};
    // This data will be available when it will be accessed in library mode
    const { currentOrgDetails: { accessibleFeatures: libModeAccessibleFeatures = [] } = {} } = cap || {};
    const hideEngagementChannel = accessibleFeatures.includes(JP_LOCALE_HIDE_FEATURE) || libModeAccessibleFeatures.includes(JP_LOCALE_HIDE_FEATURE);
    // Show only line and email channel content with both channel tabs if the JP_LOCALE_HIDE_FEATURE feature is enabled;
    filteredPanes = hideEngagementChannel ? filteredPanes?.filter((pane) => [EMAIL, LINE, ASSETS].includes(pane?.key) && pane) : filteredPanes;
    defaultChannel = hideEngagementChannel ? EMAIL : defaultChannel;

    // If audience is anonymous, prefer mobilepush as default (if not hidden)
    if (isAnonymousType) {
      const mobilePushNorm = normalizeChannel(MOBILE_PUSH.toLowerCase());
      if (!normalizedChannelsToHideSet.has(mobilePushNorm)) {
        defaultChannel = MOBILE_PUSH.toLowerCase();
      }
    }

    const defaultChannelOrder = [SMS.toLowerCase(), EMAIL, MOBILE_PUSH.toLowerCase(), LINE, CALL_TASK.toLowerCase()];
    if (normalizedChannelsToDisableSet.size > 0) {
      defaultChannelOrder.some((ch) => {
        if (!normalizedChannelsToDisableSet.has(ch)) {
          defaultChannel = ch;
          return true;
        }
        return false;
      });
    }

    const panes = this.setChannelContent(defaultChannel, filteredPanes);

    this.state = {
      selectedChannel: defaultChannel,
      panes,
    };
    if (!isFullMode) {
      onChannelChange(defaultChannel);
    }
  }

  componentDidMount() {
    const queryItems = getObjFromQueryParams(location.search);
    if (queryItems.channel === WHATSAPP) {
      this.channelChange(WHATSAPP);
    }
    if (this.props?.isFullMode) {
      this.props.templateActions.getCdnTransformationConfig();
    }
  }

  componentWillReceiveProps(nextProps) {
    if (this.props.channel !== nextProps.channel) {
      const panes = this.setChannelContent(nextProps.channel, this.state.panes);
      this.setState({selectedChannel: nextProps.channel, panes });
    }
  }
  getTemplateDataForGrid = ({templates, handlers, filterContent, channel, isLoading, loadingTip}) => {
    const currentChannel = channel.toUpperCase();
    const cardDataList = templates.map((template) => {
      const templateData =
        {
          key: `${currentChannel}-card-${template.name}`,
          title: <span title={template.name} >{template.name}</span>,
          extra: [<CapIcon type="eye" onClick={() => { if (this.props.isFullMode) { handlers.handlePreviewClick(template); } else { this.props.handlePeviewTemplate(template); } }} />],
          hoverOption: <CapButton onClick={(e) => handlers.handleEditClick(e, template._id)}>{this.props.intl.formatMessage(this.props.isFullMode ? messages.edit : messages.select)}</CapButton>,
        };
      if (currentChannel === "SMS") {
        templateData.content = template.versions.base['sms-editor'];
      } else if (currentChannel === "EMAIL") {
        templateData.url = template.versions.base.preview_http_url;
      }
      return templateData;
    });
    return (<div>
      {filterContent}
      <CapSpin spinning={isLoading} tip={loadingTip}>
        <div className="v2-pagination-container">
          <CapCustomCardList key={`${currentChannel}-card-list`} cardList={cardDataList} type={currentChannel} />
        </div>
      </CapSpin>

    </div>);
  }
  getGalleryComponent = (location) => <Gallery location={location} isFullMode={this.props.isFullMode}/>
  getCallTaskComponent = () => (
    <CallTask
      onCreateNew={this.props.createNew}
      onCallTaskSubmit={this.props.onCallTaskSubmit}
      isFullMode={this.props.isFullMode}
    />
  );

  getFacebookComponent = () => {
    const { messageDetails, cap, onFacebookSubmit,
      messageStrategy,
      showDisabledFBInfo,
      orgUnitId,
      onSelectTemplate } = this.props;
    return (
      <Facebook
        {...this.props}
        messageDetails={messageDetails}
        cap={cap}
        onFacebookSubmit={onFacebookSubmit}
        messageStrategy={messageStrategy}
        showDisabledFBInfo={showDisabledFBInfo}
        orgUnitId={orgUnitId}
        onSelectTemplate={onSelectTemplate}
      />
    );
  }
  getViberComponent =() => (
    <Viber
      {...this.props}
      isCreateFlow
    ></Viber>
  )
  getLineComponent = () => (
    <Line
      {...this.props}
      isCreateFlow
      />
    )

  getFTPComponent = () => (
    <FTP mode={this.props.FTPMode} {...this.props} />
  );

  getTemplatesComponent(channel) {
    // const templates = this.props.Templates[`${channel}Templates`];
    let query = {};
    const {isFullMode, messageStrategy, smsRegister} = this.props;
    if (!isFullMode) {
      query = {type: 'embedded', module: 'library'};
      switch (channel) {
        case 'line':
          return this.getLineComponent();
        case 'ftp':
          return this.getFTPComponent();
        default:
          break;
      }
    }
    if (messageStrategy !== "X_ENGAGE" && channel === 'facebook' && !isFullMode) {
      return this.getFacebookComponent();
    }
    const location = {pathname: `/${channel}`, search: '', query};
    switch (channel) {
      case 'call_task':
        return this.getCallTaskComponent();
      case 'assets':
        return this.getGalleryComponent(location);
      default:
        return (<Templates
          key={channel}
          location={location}
          route={{name: channel}}
          router={this.props.router}
          isFullMode={this.props.isFullMode}
          createNew={this.props.createNew}
          onSelectTemplate={(id) => this.props.onSelectTemplate(this.selectTemplate(id))}
          renderNewCardGrid={this.getTemplateDataForGrid}
          handlePeviewTemplate={this.props.handlePeviewTemplate}
          messageStrategy={this.props.messageStrategy}
          smsRegister={smsRegister}
          hideTestAndPreviewBtn={this.props.hideTestAndPreviewBtn}
    />);
    }
  }

  setChannelContent = (selectedChannel, argsPanes) => (
    argsPanes.map((pane) => {
      let content = null;
      if (pane.key === selectedChannel) {
        const channel = selectedChannel === "mpush" ? "mobilepush" : selectedChannel;
        content = this.getTemplatesComponent(channel);
      }
      return {
        ...pane,
        content,
      };
    })
  );

  channelChange = (selectedChannel) => {
    const panes = this.setChannelContent(selectedChannel, this.state.panes);
    this.setState({panes, selectedChannel}, () => { if (!this.props.isFullMode) this.props.onChannelChange(selectedChannel); });
  }
  selectTemplate = (id) => find(this.props.TemplatesList, {_id: id})

  isLoading() {
    return this.props.Templates.loadingTemplates;
  }
  render() {
    const { isFullMode, className, cap = {}, Global = {}} = this.props;
    const { accessiblePermissions = []} = cap.user || Global.user || {};
    let isCreativeAccessible = true;
    if (!accessiblePermissions.includes(CREATIVES_UI_VIEW)) {
      isCreativeAccessible = false;
    }
    return (
      !isCreativeAccessible ? <AccessForbidden /> : (
        <div className={`${className} creatives-templates-container ${isFullMode ? 'fullmode' : 'library-mode'}`} data-testid="cap-wrapper">
          {isFullMode && <Helmet
            title={this.props.intl.formatMessage(messages.creatives)}
            meta={[
              { name: 'description', content: this.props.intl.formatMessage(messages.creativesDesc) },
            ]}
          />}
          <div className="component-wrapper">
            {isFullMode && <CapHeader title={<FormattedMessage {...messages.creatives}/>} description={<FormattedMessage {...messages.creativesDesc}/>}/>}
            <StyledCapTab
              panes={this.state.panes}
              onChange={this.channelChange}
              activeKey={this.state.selectedChannel}
              defaultActiveKey={this.state.selectedChannel}
              isFullMode={isFullMode}
            />
          </div>
        </div>
      )
    );
  }
}

TemplatesV2.propTypes = {
  router: PropTypes.object,
  isFullMode: PropTypes.bool,
  onSelectTemplate: PropTypes.func,
  createNew: PropTypes.func,
  channel: PropTypes.string,
  Templates: PropTypes.object,
  TemplatesList: PropTypes.arrayOf(PropTypes.object),
  handlePeviewTemplate: PropTypes.func,
  onCallTaskSubmit: PropTypes.func,
  intl: intlShape,
  onChannelChange: PropTypes.func,
  channelsToHide: PropTypes.array,
  className: PropTypes.string.isRequired,
  channelsToDisable: PropTypes.array,
  onFacebookSubmit: PropTypes.func,
  messageDetails: PropTypes.object,
  cap: PropTypes.object,
  authData: PropTypes.object,
  FTPMode: PropTypes.string,
  messageStrategy: PropTypes.string,
  currentOrgDetails: PropTypes.object,
  restrictPersonalization: PropTypes.bool,
  isAnonymousType: PropTypes.bool,
};

TemplatesV2.defaultProps = {
  isFullMode: true,
  currentOrgDetails: {},
};

const mapStateToProps = createStructuredSelector({
  Global: makeSelectAuthenticated(),
  Templates: makeSelectTemplates(),
  TemplatesList: makeSelectTemplatesResponse(),
  currentOrgDetails: selectCurrentOrgDetails(),
});

function mapDispatchToProps(dispatch) {
  return {
    actions: bindActionCreators(actions, dispatch),
    templateActions: bindActionCreators(templateActions, dispatch),
  };
}

const withConnect = connect(mapStateToProps, mapDispatchToProps);


export default compose(
  UserIsAuthenticated,
  withConnect,
)(injectIntl(withStyles(TemplatesV2, styles)));
