import { hot } from 'react-hot-loader/root';
import React, { lazy, Suspense, useEffect, useState } from 'react';
import { useDispatch } from 'react-redux';
import { ThunkDispatch } from 'redux-thunk';
import { AnyAction } from 'redux';
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';
import { DndProvider } from 'react-dnd';
import Backend from 'react-dnd-html5-backend';
import Loading from 'components/Loading';
import NotFound from './containers/404';
import { ConfigProvider, Modal } from '@easyv/antd';
import zhCN from '@easyv/antd/lib/locale-provider/zh_CN';
import { getUserInfo } from './models/user';
import TenantModal from 'components/TenantModal';
import UsersModal from 'components/UsersModal';
import { request } from 'utils/fetch';
import { api } from 'constants/config';
import UpdateVersionModal from 'components/UpdateVersionModal';
import EasyvOfflineNot from 'components/EasyvOfflineNot';
import { collectDataFetch, getAssetsUrl } from 'utils/utils';
import { getSpace } from 'models/space';
import EasyvModal, { useConfirmRef } from 'components/EasyvModal';
import { getTransferinfo } from 'models/transfer';
import UserLock from './containers/UserLock';
import { UserInfo } from 'models/user.types';

const ScreenListLayout = lazy(
  () => import(/* webpackChunkName: "screen-list" */ './containers/screen-list'),
);
const DataSourceList = lazy(
  () => import(/* webpackChunkName: "data-source-list" */ './containers/data-source-list'),
);
const ScreenEdit = lazy(
  () => import(/* webpackChunkName: "screen-edit" */ './containers/screen-edit'),
);
const ScreenDetail = lazy(
  () => import(/* webpackChunkName: "screen-detail" */ './containers/screen-detail'),
);
const ScreenTemplate = lazy(
  () => import(/* webpackChunkName: "screen-template" */ './containers/screen-template'),
);
const Login = lazy(() => import(/* webpackChunkName: "login" */ './containers/login'));
const UserList = lazy(() => import(/* webpackChunkName: "user-list" */ './containers/user-list'));
const Certificate = lazy(
  () => import(/* webpackChunkName: "certificate" */ './components/Certificate'),
);
const Transfer = lazy(() => import(/* webpackChunkName: "certificate" */ './components/Transfer'));
const AdminPanel = lazy(
  () => import(/* webpackChunkName: "admin-panel" */ './containers/admin-panel'),
);
const InteractionList = lazy(
  () => import(/* webpackChunkName: "interaction-list" */ './containers/interaction-list'),
);
const InteractionEdit = lazy(
  () => import(/* webpackChunkName: "interaction-edit" */ './containers/interaction-edit'),
);
const InteractionPreview = lazy(
  () => import(/* webpackChunkName: "interaction-preview" */ './containers/interaction-preview'),
);
const InteractionDetail = lazy(
  () => import(/* webpackChunkName: "interaction-detail" */ './containers/interaction-detail'),
);
const MobileList = lazy(
  () => import(/* webpackChunkName: "mobile-list" */ './containers/mobile-list'),
);
const PanelDetail = lazy(
  () => import(/* webpackChunkName: "panel-detail" */ './containers/panel-detail'),
);
const AppDetail = lazy(
  () => import(/* webpackChunkName: "app-detail" */ './containers/app-detail'),
);
const TenantConstant = lazy(
  () => import(/* webpackChunkName: "party-constant" */ './containers/tenant-constant'),
);
const TrashPage = lazy(
  () =>
    import(/* webpackChunkName: "party-constant" */ './containers/screen-list/components/Trash'),
);
const ScreenListPage = lazy(
  () =>
    import(/* webpackChunkName: "party-constant" */ './containers/screen-list/components/Screens'),
);
const MainLayout = lazy(
  () => import(/* webpackChunkName: "main-layout"*/ './components/MainLayout'),
);
const AdminSpace = lazy(
  () => import(/* webpackChunkName: "AdminSpace"*/ './containers/admin-space'),
);
const RouteruAthority = lazy(
  () => import(/*webpackChunkName:"routerAuthority"*/ './containers/router-authority'),
);
const Resource = lazy(() => import(/*webpackChunkName:"resource"*/ './containers/resource'));
const SpaceShipList = lazy(
  () => import(/*webpackChunkName:"spaceship/list"*/ './containers/spaceship/list'),
);
const SpaceShipEdit = lazy(
  () => import(/*webpackChunkName:"spaceship/edit"*/ './containers/spaceship/edit'),
);
const SpaceShipPreview = lazy(
  () => import(/*webpackChunkName:"spaceship/preview"*/ './containers/spaceship/preview'),
);

const CustomLoading = () => {
  const hideLoading = /(\/bigscreen\/[0-9]+)|(\/sharescreen\/[\w=]+)$/i.test(
    window.location.pathname,
  );
  return hideLoading ? null : <Loading />;
};
// 创建
const evt = new CustomEvent('IS_ENV_DETECTION');
// eslint-disable-next-line @typescript-eslint/ban-types
type State = {};
type AppDispatch = ThunkDispatch<State, any, AnyAction>;

function App() {
  const [loading, setLoading] = useState(true);
  useEffect(() => {
    request(api.platform).then((res) => {
      window.appConfig = {
        LOCAL: res.local,
        REFRESH_TIME: res.refreshTime,
        ASSETS_URL: res.assetsUrl,
        SERVICE_URL: res.serviceUrl,
        ICON: res.icon,
        LOGO: res.logo,
        LOGIN_LOGO: res.loginLogo,
        LOGIN_URL: res.loginUrl,
        LOGOUT_URL: res.logoutUrl,
        HOME_URL: res.homeUrl,
        MARKET_URL: res.marketUrl,
        USER_ENV: res.userEnv,
        USER_CENTER_URL: res.userCenterUrl,
        UPLOAD_MODE: res.uploadMode,
        IS_ENV_DETECTION: res.envDetection,
      };
      Object.freeze(window.appConfig); //冻结
      if (window.appConfig.ICON) {
        const link: HTMLLinkElement | null = document.querySelector("link[rel*='Shortcut']");
        if (link) {
          link.type = 'image/x-icon';
          link.href = getAssetsUrl(window.appConfig.ICON);
        }
      }

      setTimeout(() => {
        document.dispatchEvent(evt);
      }, 1000);
      setLoading(false);
    });
  }, []);

  if (loading) {
    return <CustomLoading />;
  }

  return (
    <ConfigProvider locale={zhCN} prefixCls="easyv">
      <DndProvider backend={Backend}>
        <Router basename={BASENAME}>
          <Suspense fallback={<CustomLoading />}>
            <UpdateVersionModal />
            <EasyvOfflineNot />
            <Switch>
              <PrivateRoute
                exact
                path={[
                  '/',
                  '/resource',
                  '/source',
                  '/app',
                  '/admin',
                  '/constants',
                  '/users',
                  '/screens/trash',
                  '/spaceshipList',
                ]}>
                <MainLayout>
                  <Switch>
                    <Route exact path={['/', '/screens/trash']}>
                      <ScreenListLayout>
                        <Route exact path="/" render={() => <ScreenListPage />} />
                        <Route exact path="/screens/trash" render={() => <TrashPage />} />
                      </ScreenListLayout>
                    </Route>
                    <Route exact path="/source" render={() => <DataSourceList />} />
                    <Route
                      exact
                      path="/app"
                      render={() => (
                        <RouteruAthority>
                          <InteractionList />
                        </RouteruAthority>
                      )}
                    />
                    <Route exact path="/admin" render={() => <AdminPanel />} />
                    <Route exact path="/resource" render={() => <Resource />} />
                    <Route
                      exact
                      path="/constants"
                      render={() => (
                        <RouteruAthority>
                          <TenantConstant />
                        </RouteruAthority>
                      )}
                    />

                    <Route exact path="/spaceshipList" render={() => <SpaceShipList />} />

                    <LocalRoute exact path="/users" render={(props) => <UserList {...props} />} />
                  </Switch>
                </MainLayout>
              </PrivateRoute>
              <PrivateRoute
                exact
                path={[
                  '/create/:screenId',
                  '/create/:screenId/:panelId/:stateId',
                  '/node/view/:screenId',
                ]}
                render={(props) => <ScreenEdit {...props} />}
              />
              <PrivateRoute
                exact
                path="/space"
                render={() => (
                  <RouteruAthority>
                    <AdminSpace />
                  </RouteruAthority>
                )}
              />
              <PrivateRoute
                exact
                path="/template"
                render={(props) => <ScreenTemplate {...props} />}
              />
              <PrivateRoute
                exact
                path="/spaceShipEdit/:id"
                render={(props) => <SpaceShipEdit {...props} />}
              />
              <PrivateRoute
                exact
                path="/spaceShipPreview/:id"
                render={(props) => <SpaceShipPreview {...props} />}
              />
              <PrivateRoute
                exact
                path="/bigscreen/:id"
                render={(props) => <ScreenDetail {...props} />}
              />
              <PrivateRoute
                exact
                path="/panel/:screenId/:panelId/:stateId"
                render={(props) => <PanelDetail {...props} />}
              />
              <PrivateRoute
                exact
                path={['/app/edit/:appId/:pageId', '/app/edit/:appId/:pageId/:panelId/:stateId']}
                render={(props) => <InteractionEdit {...props} />}
              />
              <PrivateRoute
                exact
                path="/app/preview/:appId"
                render={(props) => <InteractionPreview {...props} />}
              />
              <PrivateRoute exact path="/mobile" render={(props) => <MobileList {...props} />} />
              <Route exact path="/sharescreen/:id" render={() => <ScreenDetail />} />
              <Route exact path="/sharedPortal/:id" render={() => <SpaceShipPreview />} />
              <Route
                exact
                path="/app/detail/:appId"
                render={(props) => <InteractionDetail {...props} />}
              />
              <Route exact path="/insert/screen/:id" render={() => <AppDetail />} />
              <Route exact path="/active" render={() => <Certificate />} />
              <LocalRoute exact path="/login" render={(props) => <Login {...props} />} />
              <PrivateRoute
                exact
                path="/qianyi"
                render={() => (
                  <RouteruAthority>
                    <Transfer />
                  </RouteruAthority>
                )}
              />
              <Route exact path="/userLock" component={UserLock} />
              <Route component={NotFound} />
            </Switch>
          </Suspense>
        </Router>
      </DndProvider>
    </ConfigProvider>
  );
}

const PrivateRoute = (props) => {
  const [initialize, setInit] = useState(false);
  const [userInfo, setUserInfo] = useState<UserInfo | null>(null);
  const warningModalRef = useConfirmRef();
  const [showTenantSelect, setShow] = useState(false);
  const dispatch: AppDispatch = useDispatch();
  const isNeedUserInfo = !/\/active|\/404|\/login|\/shareScreen\/*/i.test(window.location.pathname);

  useEffect(() => {
    const visibilitychange = async () => {
      Modal.destroyAll();
      if (!document.hidden && isNeedUserInfo) {
        const spaceId = sessionStorage.getItem('spaceId');
        const result: any = await dispatch(getSpace('update'));
        if (result) {
          const item = result.find((d) => d.isUsing);
          const newSpaceId = item && item.id;
          if (newSpaceId && newSpaceId != spaceId) {
            if (/(\/app\/edit)|(\/create\/[0-9]+)/.test(window.location.pathname)) {
              warningModalRef.current?.show();
            }
          }
        }
      }
    };

    document.addEventListener('visibilitychange', visibilitychange);
    if (isNeedUserInfo) {
      dispatch(getSpace());
    }

    return () => {
      document.removeEventListener('visibilitychange', visibilitychange);
    };
  }, []);

  useEffect(() => {
    isNeedUserInfo &&
      dispatch(getUserInfo()).then((data) => {
        if (data) {
          if (data === 1) {
            setShow(true);
          } else {
            const { tenantId } = data;
            localStorage.setItem('lastTenantId', tenantId);
          }
          setInit(true);
          setUserInfo(data);
        }
      });
  }, []);

  useEffect(() => {
    if (window.appConfig.LOCAL && !isNeedUserInfo) {
      dispatch(getTransferinfo());
    }
  }, []);

  useEffect(() => {
    collectDataFetch();
  }, [window.location.pathname]);

  if (!initialize) {
    return null;
  }

  if (showTenantSelect) {
    return window.appConfig.USER_ENV === 'uic' ? (
      <TenantModal defaultVisible={true} />
    ) : window.appConfig.USER_ENV === 'local' ? (
      <UsersModal defaultVisible={true} />
    ) : null;
  }

  if (
    /(\/qianyi)|(\/active)/.test(window.location.pathname) &&
    window.appConfig.USER_ENV !== 'local'
  ) {
    return <Route component={NotFound} />;
  }

  if (
    /(\/users)|(\/admin)|(\/resource)|(\/space)$/.test(window.location.pathname) &&
    userInfo?.type === 'education'
  ) {
    return <Route component={NotFound} />;
  }

  return (
    <>
      <Route {...props} />
      <EasyvModal.Confirm
        title="警告"
        iconType="info"
        onOk={() => {
          window.location.href = `${BASENAME || '/'}`;
        }}
        onOkBtnType="primary"
        content="空间状态发生变更，是否返回首页？"
        ref={warningModalRef}
      />
    </>
  );
};

const LocalRoute = (props) => {
  if (window.appConfig.USER_ENV !== 'local') {
    return null;
  }

  return <Route {...props} />;
};

export default hot(App);
