import PropTypes from 'prop-types';
import React from 'react';
import Helmet from 'react-helmet';
import { connect } from 'react-redux';
import { CapNotification, CapModal, CapSnackBar, CapSomethingWentWrong } from '@capillarytech/cap-ui-library';
import { bindActionCreators, compose } from 'redux';
import styled from 'styled-components';
import { createStructuredSelector } from 'reselect';
import _ from 'lodash';
import moment from 'moment';
// import 'moment/locale/zh-cn';
import { GA, multipleOrgSwitch, utilsSessionStorageApi, Auth } from '@capillarytech/cap-ui-utils';
import { injectIntl, FormattedMessage, intlShape, FormattedHTMLMessage } from 'react-intl';
import messages from './messages';
import { makeSelectAuthenticated, makeSelectUser, makeSelectDemoVideoAndLink } from './selectors';
import * as actions from './actions';
import * as locationActions from '../LanguageProvider/actions';
import * as appActions from '../App/actions';
import config from '../../config/app';
import NavigationBar from '../../v2Components/NavigationBar';
import { publicPath } from '../../config/path';
import { GTM_TRACKING_ID, CREATIVES_UI_VIEW, FAILURE } from '../App/constants';
import { makeSelectLocale } from '../../v2Containers/LanguageProvider/selectors';
import CapSupportVideosWrapper from '@capillarytech/cap-ui-library/CapSupportVideosWrapper';
import { replaceDynamicAndCompare } from '@capillarytech/cap-ui-library/CapSupportVideosWrapper/utils';
import {
  ORG_SETTINGS_URL,
  ORG_REFRESH_SEC,
  ORG_CHANGED,
  REQUEST,
  DEFAULT,
  ENABLE_PRODUCT_SUPPORT_VIDEOS,
} from './constants';
import './_cap.scss';
import { Switch } from 'react-router';
import componentRoutes from '../../routes';
import RenderRoute from '../../v2Components/RenderRoute';
import injectReducer from '../../utils/injectReducer';
import injectSaga from '../../utils/injectSaga';
import reducer from './reducer';
import zaloReducer from '../Zalo/reducer';
import { capSagaLiquidEntity, v2CapSagas } from './sagas';
import { v2SmsCreateSagas } from '../Sms/Create/sagas';
import { v2EbillSagas } from '../Ebill/sagas';
import { v2EmailDuplicateTemplateSaga } from '../Email/sagas';
import { v2LineContainerSagas } from '../Line/Container/sagas'
import { v2MobilePushCreateSagas } from '../MobilePush/Create/sagas';
import { v2WechatMapTemplatesSagas } from '../WeChat/MapTemplates/sagas';
import { v2RcsSagas } from '../Rcs/sagas';
import { v2InAppSagas } from '../InApp/sagas'; 
import { v2ViberSagas } from '../Viber/sagas';
import { v2FacebookSagas } from '../Facebook/sagas';
import createReducer from '../Line/Container/reducer';
import { DAEMON } from '@capillarytech/vulcan-react-sdk/utils/sagaInjectorTypes';
const gtm = window.dataLayer || [];
const {
  logNewTab,
  utilsGetOrgNameFromId,
  tabBeforeUnloadEventHandler,
  utilsHandleStorageChange,
  isMultipleTabsOpen,
} = multipleOrgSwitch;
const {
  loadSessionItem,
  saveSessionItem,
} = utilsSessionStorageApi;

const CapWrapper = styled.div`
  margin: 0 auto;
  display: flex;
  min-height: 100%;
  padding: 0;
  flex-direction: column;
`;
GA.initialize({ accessKey: GTM_TRACKING_ID, trackUIError: true, trackLoadPerformance: 'creatives' });

const MainWrapper = styled.div`
  position: relative;
  min-height: calc(100vh - 5.29rem);
  top: 4.72rem;
`;

const ContentWrapper = styled.div`
  && {
    margin-left: ${(props) => (props.leftNavbarExpanded ? '17rem' : '4.475rem')};
  }
`;

export class Cap extends React.Component { // eslint-disable-line react/prefer-stateless-function

  constructor(props) {
    super(props);
    this.state = {
      switchedOrg: false,
      isCreativesAccessible: true,
      refreshSeconds: ORG_REFRESH_SEC,
      selectedOrgId: null,
      showRefreshModal: false,
      showOrgChangeModal: false,
      localStorageOrgInfo: { oldValue: null, newValue: null },
      leftNavbarExpanded: false,
    };
    this.changeOrg = this.changeOrg.bind(this);
    this.logout = this.logout.bind(this);
    this.handleRemoveMessage = this.handleRemoveMessage.bind(this);
    this.getMappedLocale = this.getMappedLocale.bind(this);
  }

  componentWillMount() {
    const { pathname } = this.props.location;
    const parentModule = pathname.substring(pathname.lastIndexOf('/') + 1);
    this.props.actions.getUserData((userData, currentOrgDetails = {}) => { //taking currentOrgDetails as we are not getting this data in this.props.Global props.
      const { accessibleFeatures = [] } = currentOrgDetails;
      if (!userData.accessiblePermissions.includes(CREATIVES_UI_VIEW)) {
        this.setState({ isCreativesAccessible: false });
      }
      const userGtmData = this.getUserGtmData();
      this.setDimensionData(userGtmData);
      gtm.push({ ...userGtmData, event: 'userAuthenticated' });
      Auth.initialize({
        permissions: userData.accessiblePermissions,
        isCapUser: userData.isCapUser,
        roles: Object.keys(userData.accessRoles),
        accessibleFeatures,
      });
    });
    this.props.actions.getTopbarMenuData(parentModule);
    if (this.props.Global.orgID !== undefined) {
      gtm.push({ orgId: this.props.Global.orgID });
    }
    if (this.props.Global.isLoggedIn) {
      if (this.props.Global.user && Object.keys(this.props.Global.user).length) {
        // gtm.push({userId: this.props.Global.user.id});
        this.props.appActions.getSidebar();
      }
    }
  }

  componentDidMount() {
    const user = localStorage.getItem('user');
    let locale = 'en';
    if (user) {
      locale = JSON.parse(user).lang;
    }
    locale = this.getMappedLocale(locale);
    //locale = 'zh';
    this.props.actions.getSupportVideosConfig();
    moment.locale(locale);
    window.addEventListener('storage', this.handleStorageChange, false);
    document.addEventListener(
      'visibilitychange',
      this.handleVisibilityChange,
      false,
    );
    window.addEventListener('pageshow', this.tabOnloadEventHandler, false);
    window.addEventListener('pagehide', tabBeforeUnloadEventHandler, false);
  }

  componentWillReceiveProps(nextProps) {
    const user = this.props.Global.user;
    const nextPropsUser = nextProps.Global.user;
    if (!nextProps.Global.settingProxyOrg && nextProps.Global.changeProxyOrgSuccess &&
      !_.isEqual(nextProps.Global.changeProxyOrgSuccess, this.props.Global.changeProxyOrgSuccess) && !this.state.switchedOrg) {
      this.navigateToDashboard();
    }

    const callBack = nextProps?.routeParams?.callbackUrl ? decodeURIComponent(nextProps?.routeParams?.callbackUrl) : "";
    if (nextProps.Global.error) {
      const locationValue = `${window.location.origin}${callBack}?flash=${nextProps.Global.error}`;
      window.location.replace(locationValue);
      window.location.reload();
    }

    if (nextPropsUser && user && nextProps.Global.isLoggedIn && nextProps.Global.isLoggedIn !== this.props.Global.isLoggedIn) {
      this.props.appActions.getSidebar();
    }
  }

  componentDidUpdate(prevProps) {
    if (
      !(prevProps.Global.currentOrgDetails) &&
      this.props.Global.currentOrgDetails &&
      loadSessionItem(ORG_CHANGED)
    ) {
      this.showOrgChangeSnackBar();
    }
  }

  componentWillUnmount() {
    this.setState({ switchedOrg: false });
    this.props.actions.clearTopbarMenuData();
    window.removeEventListener('storage', this.handleStorageChange, false);
    document.removeEventListener(
      'visibilitychange',
      this.handleVisibilityChange,
      false,
    );
    window.removeEventListener(
      'pageshow',
      this.tabOnloadEventHandler,
      false,
    );
    window.removeEventListener(
      'pagehide',
      tabBeforeUnloadEventHandler,
      false,
    );
  }

  tabOnloadEventHandler = () => {
    logNewTab();
  }

  setDimensionData(userGtmData) {
    Object.values(userGtmData).forEach((value, index) => {
      GA.setCustomDimension({ [`dimension${index + 1}`]: value });
    });
  }
  getUserGtmData(props) {
    const selectedProps = props || this.props;
    const { user: userData, orgID, currentOrgDetails} = selectedProps?.Global || {};
    const {
      basic_details: {
        base_country: orgBaseCountry = '',
        base_currency: orgBaseCurrency = '',
        base_language: orgBaseLanguage = '',
      } = {},
    } = currentOrgDetails || {};
    if (userData) {
      const {
        attributes: {
          USERNAME: userName,
          EMAIL: userEmail,
        } = {},
        proxyOrgList = [],
        isCapUser,
        refID,
        type: userRole = '',
        orgName: userOrgName,
      } = userData;
      const { orgName } = _.find(proxyOrgList, { orgID }) || {
        orgName: userOrgName,
      };
      const gtmData = {
        isCapUser,
        orgId: orgID,
        orgName,
        userId: refID,
        userName: userName?.value,
        userEmail: userEmail?.value,
        userRole,
        orgBaseCountry,
        orgBaseCurrency,
        orgBaseLanguage,
        domainName: userEmail?.value?.split('@').pop(),
      };
      return gtmData;
    }
    return {};
  }

  getMappedLocale(locale) {
    const map = {
      'en': 'en-US',
      'zh-cn': 'zh',
      'en-US': 'en-US',
      'zh': 'zh',
    };
    return map[locale];
  }

  handleRemoveMessage(messageIndex) {
    this.props.actions.removeMessageFromQueue(messageIndex);
  }

  navigateToDashboard() {
    const dashboardUrl = process.env.NODE_ENV === 'production' ? config.production.dashboard_url_v2 : config.development.dashboard_url_v2;
    this.props.router.push({ pathname: dashboardUrl, state: {} });
    this.props.router.go();
  }

  logout() {
    this.props.actions.logout();
  }
  changeOrg(orgId) {
    //display orgChangeModal if more than one tabs is open
    if (isMultipleTabsOpen()) {
      this.setState({
        showOrgChangeModal: true,
        selectedOrgId: orgId,
      });
    } else {
      this.props.actions.changeOrg(orgId);
    }
  }

  showOrgChangeSnackBar = () => {
    saveSessionItem(ORG_CHANGED, false);
    const {
      Global: {
        currentOrgDetails: {
          basic_details: { name: currentOrgName } = {},
        } = {},
      } = {},
      intl: { formatMessage } = {},
    } = this.props;
    CapSnackBar.warning({
      content: (
        <div>
          {formatMessage(messages.orgChangedText)}
          <b>
            {formatMessage(messages.newOrgName, {
              newOrgName: currentOrgName,
            })}
          </b>
        </div>
      ),
      showCloseIcon: true,
    });
  };

  handleVisibilityChange = () => {
    const activeDoc = document.hidden || false;
    const { showRefreshModal, refreshSeconds } = this.state;
    if (
      activeDoc === false &&
      showRefreshModal &&
      refreshSeconds === ORG_REFRESH_SEC
    ) {
      const timer = setInterval(() => {
        this.setState((prevState) => ({
          refreshSeconds: prevState.refreshSeconds - 1,
        }));
      }, 1000);
      setTimeout(() => {
        clearInterval(timer);
        saveSessionItem(ORG_CHANGED, true);
        this.navigateToDashboard();
      }, refreshSeconds * 1000);
    }
  };

  handleStorageChange = (e) => {
    const { oldValue, newValue } = e;
    if (utilsHandleStorageChange(e, 'orgID')) {
      const localStorageOrgInfo = { oldValue, newValue };
      this.setState({ showRefreshModal: true, localStorageOrgInfo });
    }
  };

  getOrgNameFromId = (orgId) => {
    const {
      Global: {
        user: {
          proxyOrgList,
          orgName: defaultOrgName,
          orgID: defaultOrgID,
        } = {},
      } = {},
    } = this.props;
    return utilsGetOrgNameFromId(
      orgId,
      proxyOrgList,
      defaultOrgID,
      defaultOrgName,
    );
  };

  renderOrgRefreshModal = () => {
    const {
      localStorageOrgInfo: { oldValue: oldOrgId, newValue: newOrgId } = {},
      showRefreshModal,
      refreshSeconds,
    } = this.state;
    const { intl: { formatMessage } = {} } = this.props;
    const oldOrgName = this.getOrgNameFromId(Number(oldOrgId));
    const newOrgName = this.getOrgNameFromId(Number(newOrgId));
    // some users do not have entry for their default org in proxyOrgList.
    // getOrgNameFromId returns back orgID if no matching entry is present in proxyOrgList
    // so replacing with defaultOrgName if defaultOrgID is returned
    const modalData = (
      <CapModal
        title={formatMessage(messages.orgRefreshHeading)}
        visible={showRefreshModal}
        closable={false}
        centered
        maskClosable={false}
        footer={null}
      >
        <div className="modal-body">
          <span className="title">
            <FormattedHTMLMessage
              {...messages.refreshOrgText}
              values={{ oldOrgName, newOrgName }}
            />
          </span>
          <div className="content seconds-right">
            {formatMessage(messages.refreshText, {
              time: `${refreshSeconds}s`,
            })}
          </div>
        </div>
      </CapModal>
    );
    return modalData;
  };

  renderOrgChangeModal = () => {
    const { selectedOrgId, showOrgChangeModal } = this.state;
    const {
      Global: {
      currentOrgDetails: { basic_details: { name: oldOrgName } = {} } = {},
      },
      intl: { formatMessage } = {},
    } = this.props;
    const newOrgName = this.getOrgNameFromId(selectedOrgId);
    // some users do not have entry for their default org in proxyOrgList.
    // getOrgNameFromId returns back orgID if no matching entry is present in proxyOrgList
    // so replacing with defaultOrgName if defaultOrgID is returned
    return (
      <CapModal
        className="change-org-confirm"
        title={formatMessage(messages.areYouSureText)}
        visible={showOrgChangeModal}
        onOk={this.handleOrgChangeOk}
        onCancel={this.handleOrgChangeCancel}
        centered
        okText={formatMessage(messages.changeOk)}
        cancelText={formatMessage(messages.cancel)}
      >
        <FormattedHTMLMessage
          {...messages.orgChangeText}
          values={{ oldOrgName, newOrgName }}
        />
      </CapModal>
    );
  };

  handleOrgChangeOk = () => {
    const { selectedOrgId: orgId } = this.state;
    if (orgId !== null) {
      this.props.actions.changeOrg(orgId);
      this.setState({ showOrgChangeModal: false });
    }
  };

  handleOrgChangeCancel = () => {
    this.setState({ showOrgChangeModal: false });
  };

  renderNavigationComponent(component) {
    const { demoVideoAndLinkJSONData: {
        demoVideoAndLinkJSON = {},
        demoVideoAndLinkJSONStatus,
      } = {},
      Global,
    } = this.props;
    const { currentOrgDetails = {}, user = {} } =
    Global || {};
    const { lang: userLocale = '' } = user;
    let wrapperComponent = <>{component}</>;
    const {
      basicDetails: { base_language: orgLocale = '' } = {},
      accessibleFeatures = [],
    } = currentOrgDetails || {};
    if (
      accessibleFeatures.includes(
        ENABLE_PRODUCT_SUPPORT_VIDEOS
      ) &&
      demoVideoAndLinkJSON?.is_active &&
      demoVideoAndLinkJSONStatus !== REQUEST
    ) {
      const demoLocale = userLocale || orgLocale || DEFAULT;
      const JSONInContext = demoVideoAndLinkJSON?.json_config;
      const currentPathJSON = JSONInContext?.find((routeEle) =>
        replaceDynamicAndCompare(location?.pathname, routeEle?.route),
      );
      const targetElements = currentPathJSON?.target_elements || {};
      wrapperComponent = (
        <CapSupportVideosWrapper
          targetElements={targetElements}
          locale={demoLocale}
        >
          {component}
        </CapSupportVideosWrapper>
      );
    }
    return wrapperComponent;
  }

  handleLeftNavBarExpanded = (leftNavbarExpandedProp) => {
    this.setState({leftNavbarExpanded: leftNavbarExpandedProp})
  }

  render() {
    const { Global, location } = this.props;
    const { topbarMenuData, isLoggedIn, currentOrgDetails = {}, getUserDataStatus, getUserDataCode } = Global;
    const topbarMenuDataOptions = topbarMenuData && topbarMenuData.data ? topbarMenuData.data : [];
    const type = this.props.location.query.type;
    const toastMessages = this.props.Global.messages;
    const { isCreativesAccessible, showOrgChangeModal, showRefreshModal } = this.state;
    return (
      <CapWrapper>
        { this.props.loader.localeLoading || this.props.Global.fetching_userdata ?
          <div className="cap-loader-box">
            <img
              className="loader-image"
              src="https://s3.amazonaws.com/fileservice.in/intouch_creative_assets/88561f46de9407021cad.gif"
              alt="Capillary"/>
          </div> : <>
            <Helmet
              titleTemplate="Capillary - %s"
              defaultTitle={<FormattedMessage {...messages.appName} />}
              meta={[
            { name: 'description', content: <FormattedMessage {...messages.appName} /> },
              ]}
        />
            <div className="wrapper">
              {
                getUserDataStatus === FAILURE &&
                  getUserDataCode !== 401 &&
                    <CapSomethingWentWrong url={`${window.location.origin}${publicPath}/v2`} />
              }
              {isLoggedIn && type !== 'embedded' ?
              this.renderNavigationComponent(
                <NavigationBar
                  userData={Global}
                  changeOrg={this.changeOrg}
                  isCreativesAccessible={isCreativesAccessible}
                  logout={this.logout}
                  orgSettingsUrl={ORG_SETTINGS_URL}
                  loggedIn={isLoggedIn}
                  topbarMenuData={topbarMenuDataOptions}
                  location={location}
                  campaignOrgV2Status={currentOrgDetails.org_campaign_v2_status}
                  handleLeftNavBarExpanded={this.handleLeftNavBarExpanded}
                  leftNavbarExpandedProp={this.state.leftNavbarExpanded}
                />) : ''}
              <MainWrapper className="main">

                <ContentWrapper
                  className={`main-content ${this.state.leftNavbarExpanded ? "contet-width-collapse" : "content-width-expanded"}`}
                  leftNavbarExpanded={this.state.leftNavbarExpanded}
                >
                  <Switch>
                    {componentRoutes.map(routeProps => {
                      return (
                        <RenderRoute
                          {...routeProps}
                          key={routeProps.path}
                          isLoggedIn={isLoggedIn}
                        />
                      )}
                    )}
                  </Switch>
                </ContentWrapper>
              </MainWrapper>
            </div>
            {(toastMessages && toastMessages.length > 0) &&
          toastMessages.map((message) => {
            //If the messages are not removed then the same messages appear again
            setTimeout(this.handleRemoveMessage(message.messageIndex), (message.duration || 5) * 1000);
            return CapNotification[message.type]({message: message.text, key: message.text, duration: message.duration || 5});
          }
          )
        }
         </> }
        {showRefreshModal && this.renderOrgRefreshModal()}
        {showOrgChangeModal && this.renderOrgChangeModal()}
      </CapWrapper>
    );
  }
}

Cap.propTypes = {
  children: PropTypes.node,
  actions: PropTypes.object.isRequired,
  Global: PropTypes.object,
  router: PropTypes.object,
  appActions: PropTypes.object,
  locationActions: PropTypes.object,
  location: PropTypes.object,
  intl: intlShape.isRequired,
  demoVideoAndLinkJSONData: PropTypes.object,
};

const mapStateToProps = createStructuredSelector({
  Global: makeSelectAuthenticated(),
  User: makeSelectUser(),
  loader: makeSelectLocale(),
  demoVideoAndLinkJSONData: makeSelectDemoVideoAndLink(),
});

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

const withConnect = connect(mapStateToProps, mapDispatchToProps);
const withReducer = injectReducer({ key: 'cap', reducer });
const withZaloReducer = injectReducer({ key: 'zalo', reducer: zaloReducer });
const withSaga = injectSaga({ key: 'cap', saga: v2CapSagas });
const withLiquidSaga = injectSaga({ key: 'liquid', saga: capSagaLiquidEntity, mode : DAEMON });
const withSmsCreateSaga = injectSaga({ key: 'create', saga: v2SmsCreateSagas });
const withEbillSaga = injectSaga({ key: 'ebill', saga: v2EbillSagas });
const withEmailSaga = injectSaga({ key: 'email', saga: v2EmailDuplicateTemplateSaga });
const withLineContainerSaga = injectSaga({ key: 'lineCreate', saga: v2LineContainerSagas });
const withMobilePushCreateSaga = injectSaga({ key: 'mobileCreate', saga: v2MobilePushCreateSagas });
const withWechatMapTemplatesSaga = injectSaga({ key: 'weChatMapTemplate', saga: v2WechatMapTemplatesSagas });
const withRcsSaga = injectSaga({ key: 'rcs', saga: v2RcsSagas });
const withInAppSaga = injectSaga({ key: 'inapp', saga: v2InAppSagas, mode: DAEMON });
const withViberSaga = injectSaga({ key: 'viber', saga: v2ViberSagas });
const withFacebookSaga = injectSaga({ key: 'facebook', saga: v2FacebookSagas });
const withLineReducer = injectReducer({ key: 'lineCreate', reducer: createReducer });

export default compose(
  withSaga,
  withSmsCreateSaga,
  withEbillSaga,
  withEmailSaga,
  withLiquidSaga,
  withLineContainerSaga,
  withMobilePushCreateSaga,
  withWechatMapTemplatesSaga,
  withRcsSaga,
  withInAppSaga,
  withViberSaga,
  withFacebookSaga,
  withReducer,
  withZaloReducer,
  withLineReducer,
  withConnect,
)(injectIntl(Cap));
