import React, { useEffect } from 'react';
import ReactDOM from 'react-dom';

import { ConfigProvider, message, Modal, notification } from 'antd';
import { ConnectedRouter } from 'connected-react-router/immutable';
import Cookies from 'js-cookie';
import canUseDom from 'rc-util/lib/Dom/canUseDom';
import { updateCSS } from 'rc-util/lib/Dom/dynamicCSS';
import { Provider } from 'react-redux';

import { LocaleContainer } from '@wisdom-utils/components';
import { history } from '@wisdom-utils/runtime';
import { params, Storeage } from '@wisdom-utils/utils/lib/helpers';

import { appService } from './api';
import Container from './components/Container';
import App from './containers/App';
import { actionCreators } from './containers/App/store';
import { defaultApp, initMicroApps } from './micro';
import Login from './pages/user/login/login';
import store from './stores';
import { getToken } from './utils/utils';

const { getThemeVariables } = require('antd/dist/theme');
const defaultSetting = require('../config/defaultSetting');
const MOUNT_NODE = document.getElementById('root');
const customPrefixCls = 'panda-console-base';
// eslint-disable-next-line no-restricted-globals
const namespace = `__PANDA_STORE__${location.hostname}`;
window.createStoreage = new Storeage(namespace);

const dynamicStyleMark = `-panda-${Date.now()}-${Math.random()}`;
function getStyle(prefixCls, theme) {
  const variables = {};

  Object.keys(theme).forEach(item => {
    variables[item] = theme[item];
  });
  const cssList = Object.keys(variables).map(key => `--${prefixCls}-${key}: ${variables[key]};`);

  return `
  :root {
    ${cssList.join('\n')}
  }
  `.trim();
}

const registerTheme = function(prefixCls, theme) {
  const style = getStyle(prefixCls, theme);
  if (canUseDom()) {
    updateCSS(style, `${dynamicStyleMark}-dynamic-theme`);
  }
};

export const AppInitState = () => {
  const getClient = () => {
    const value = params.getParams('client') || sessionStorage.getItem('client');
    const client = value && value !== 'undefined' ? value : 'city';
    return client;
  };
  const getUrlToken = () => {
    const value = params.getParams('token');
    const token = value && value !== 'undefined' ? value : null;
    return token;
  };

  const client = getClient();
  const token = getUrlToken();
  if (sessionStorage.getItem('client') !== client) {
    sessionStorage.setItem('client', client);
  }
  let config = window.globalConfig || {};
  // eslint-disable-next-line no-undef, no-restricted-globals
  createStoreage.remove(`__PANDA_STORE__${location.hostname}`);

  window.globalConfig = {};
  // eslint-disable-next-line no-underscore-dangle
  window.__INITIAL_STATE__ = {};

  if (!getToken() || config.token == null) {
    // eslint-disable-next-line no-undef
    createStoreage.remove(namespace);
    config = {};
  }
  if (!params.getParams('client', window.location.search) && config) {
    // eslint-disable-next-line no-undef
    createStoreage.remove(namespace);
  }

  // eslint-disable-next-line no-undef
  if (!createStoreage.get('globalConfig')) {
    window.createStoreage = new Storeage(namespace);
  }

  if (!getToken()) {
    localStorage.removeItem('loginSite');
  }

  const initGeteWay = () => {
    appService
      .getWateWayConfig({ ignoreSite: true })
      .then(res => {
        // eslint-disable-next-line prettier/prettier, no-undef
        const hasGateWay = !res || !res.data ? false : _.isString(res.data) ? JSON.parse(res.data) : (typeof res.data === 'boolean' ? res.data : false);
        return {
          hasGateWay,
          apiGatewayDomain: `${window.location.origin}${hasGateWay ? '/PandaCore/GateWay' : ''}`,
        };
      })
      .then(gateWayConfig => {
        // eslint-disable-next-line no-use-before-define
        initGlobalConfig(gateWayConfig);
      })
      .catch(err => {
        // eslint-disable-next-line no-use-before-define
        initGlobalConfig();
      });
  };

  const initGlobalConfig = (gateWayConfig = {}) => {
    appService
      .queryConfig({
        client: client || 'city',
        ignoreSite: true,
      })
      .then(res => {
        if (res) {
          const { data } = res;
          if (!data.client) {
            data.client = client;
          }
          if (data.pwdRegex) {
            localStorage.setItem('password_pwdRegex', data.pwdRegex);
          } else {
            localStorage.removeItem('password_pwdRegex');
          }
          if (data.pwdRegexTip) {
            localStorage.setItem('password_pwdRegexTip', data.pwdRegexTip);
          } else {
            localStorage.removeItem('password_pwdRegexTip');
          }
          store.dispatch(
            actionCreators.getConfig(
              Object.assign(
                {},
                data,
                {
                  token: '',
                  access_token: '',
                  userInfo: null,
                },
                gateWayConfig,
              ),
            ),
          );
          const products = (data.products || []).map(item => {
            if (item.PackageName === 'civweb4') {
              return 'web4_console';
            }
            return `${item.PackageName}-main`;
          });

          if (products && products.length > 0) {
            Object.keys(products).forEach(item => {
              window[products[item]] &&
                window[products[item]] &&
                window[products[item]].unmount &&
                window[products[item]].unmount({ store });
            });
          }
          // eslint-disable-next-line no-new
          // 增加免登判定
          if (!token && getToken()) {
            // eslint-disable-next-line no-new
            const action = new Login(
              {
                global: Object.assign(
                  {},
                  data,
                  {
                    token: getToken(),
                  },
                  gateWayConfig,
                ),
                // eslint-disable-next-line no-shadow
                updateConfig: data => store.dispatch(actionCreators.getConfig(data)),
                isInit: false,
                logout: () => store.dispatch(actionCreators.logout()),
              },
              () => {
                // (async () => {
                //   (await (getToken() && window.globalConfig && window.globalConfig.token)) &&
                //     // eslint-disable-next-line no-use-before-define
                //     initMicroApps(loader, store);
                // })();
              },
              true,
            );
            action.events.on('loginSuccess', event => {
              window.history.pushState('', '', `/?client=${client}`);
              defaultApp();
            });
          }
          return window.globalConfig.variableTheme;
        }
      })
      .then(themeConfig => {
        ConfigProvider.config({
          prefixCls: customPrefixCls,
          theme: {
            primaryColor: themeConfig.primaryColor,
          },
        });

        registerTheme(customPrefixCls, {
          'header-bg-color': themeConfig.headerPrimaryColor,
          // 'linear-gradient(0deg, #0066d6, #39a9ff 100%)'
        });
      })
      .catch(error => {
        store.dispatch(actionCreators.getConfigError(error));
      });
  };

  const initLocale = () => {
    localStorage.setItem('umi_locale', 'zh-CN');
  };

  // 语音播报全局拦截
  const initMessageVoice = () => {
    const rawSpeak = window.speechSynthesis.speak;
    window.speechSynthesis.speak = function(...args) {
      if (
        window.globalConfig &&
        // eslint-disable-next-line no-prototype-builtins
        window.globalConfig.hasOwnProperty('messageVoice') &&
        window.globalConfig.messageVoice === false
      )
        return;
      rawSpeak.apply(window.speechSynthesis, args);
    };
  };

  // 添加主题变更事件监听
  const initAppTheme = () => {
    const hasThemeChanged = (preTheme, theme) => {
      if (!preTheme && !theme) return false;
      if (
        preTheme &&
        theme &&
        (!theme.primaryColor || theme.primaryColor === preTheme.primaryColor) &&
        (!theme.navTheme || theme.navTheme === preTheme.navTheme) &&
        (!theme.headerPrimaryColor || theme.headerPrimaryColor === preTheme.headerPrimaryColor)
      )
        return false;
      return true;
    };
    store.subscribe(
      (function() {
        const preVariableTheme = store.getState().toJS().global?.globalConfig?.variableTheme;
        return function() {
          // if (!preVariableTheme)
          const variableTheme = store.getState().toJS().global?.globalConfig?.variableTheme;
          if (!hasThemeChanged(preVariableTheme, variableTheme)) return false;
          const { primaryColor: prePrimaryColor, navTheme: preNavTheme, headerPrimaryColor: preHeaderPrimaryColor } =
            preVariableTheme || {};
          const { primaryColor, headerPrimaryColor } = variableTheme;
          if (primaryColor && primaryColor !== prePrimaryColor) {
            ConfigProvider.config({
              prefixCls: customPrefixCls,
              theme: {
                primaryColor,
              },
            });
          }
          if (headerPrimaryColor && headerPrimaryColor !== preHeaderPrimaryColor) {
            registerTheme(customPrefixCls, {
              'header-bg-color': headerPrimaryColor,
            });
          }
        };
      })(),
    );
  };
  initLocale();
  initMessageVoice();
  initGeteWay();
  initAppTheme();
};

const RootContainer = props => {
  const { loading } = props;

  useEffect(() => {
    AppInitState();
  }, []);

  const finalConfig = {
    ...{
      prefixCls: customPrefixCls,
      theme: {
        'root-entry-name': 'default',
        ...getThemeVariables({}),
        primaryColor: defaultSetting.primaryColor,
      },
    },
  };

  if (finalConfig.prefixCls) {
    ConfigProvider.config({
      rootPrefixCls: customPrefixCls,
    });
    message.config({
      rootPrefixCls: `${finalConfig.prefixCls}-message`,
    });
    notification.config({
      rootPrefixCls: `${finalConfig.prefixCls}-notification`,
    });
  }

  return React.createElement(
    Provider,
    {
      store,
    },
    React.createElement(
      ConnectedRouter,
      {
        history,
      },
      React.createElement(
        LocaleContainer,
        {
          prefixCls: customPrefixCls,
        },
        React.createElement(
          ConfigProvider,
          {
            prefixCls: customPrefixCls,
          },
          React.createElement(
            Container,
            null,
            React.createElement(App, {
              loading,
            }),
          ),
        ),
      ),
    ),
  );
};

export const render = ({ loading }) => {
  // eslint-disable-next-line react-hooks/rules-of-hooks
  ReactDOM.render(<RootContainer loading={loading} />, MOUNT_NODE);
};

// updateTheme('#ff9600');
const loader = loading => render({ loading });

export default loader;