import React, { useEffect, useMemo } from 'react';
import { useRouter } from 'next/router';
import cookies from 'next-cookies';
import Head from 'next/head';
import type { AppProps } from 'next/app';
import { Provider } from 'react-redux';
import '../style/global.less';
import { ConfigProvider, Message } from '@arco-design/web-react';
import zhCN from '@arco-design/web-react/es/locale/zh-CN';
import enUS from '@arco-design/web-react/es/locale/en-US';
import NProgress from 'nprogress';
import { GlobalContext } from '../context';
import checkLogin from '@/utils/checkLogin';
import '@/api'; // 全局挂载axios拦截器
import changeTheme from '@/utils/changeTheme';
import useStorage from '@/utils/useStorage';
import Layout from './layout';
import '../mock';
import { getUserInfo } from '@/api/user';
import { setSessionUserInfo } from '@/utils/auth';
import store from '@/store';
import { updateUserInfo } from '@/store/user';


interface RenderConfig {
  arcoLang?: string;
  arcoTheme?: string;
}

export default function MyApp({
                                pageProps,
                                Component,
                                renderConfig
                              }: AppProps & { renderConfig: RenderConfig }) {
  const { arcoLang, arcoTheme } = renderConfig;
  const [lang, setLang] = useStorage('arco-lang', arcoLang || 'zh-CN');
  const [theme, setTheme] = useStorage('arco-theme', arcoTheme || 'light');
  const router = useRouter();

  const locale = useMemo(() => {
    switch (lang) {
      case 'zh-CN':
        return zhCN;
      case 'en-US':
        return enUS;
      default:
        return zhCN;
    }
  }, [lang]);

  async function fetchUserInfo() {
    store.dispatch(updateUserInfo({ userLoading: true }));
    const res: any = await getUserInfo();
    setSessionUserInfo(res.data);
    store.dispatch(updateUserInfo({ userInfo: { ...res.data } }));
  }

  useEffect(() => {
    if (checkLogin()) {
      fetchUserInfo();
    }
    else if (window.location.pathname.replace(/\//g, '') !== 'login') {
      Message.error('token过期，请重新登录');
      window.location.pathname = '/login';
    }
  }, []);

  useEffect(() => {
    const handleStart = () => {
      NProgress.set(0.4);
      NProgress.start();
    };

    const handleStop = () => {
      NProgress.done();
    };

    router.events.on('routeChangeStart', handleStart);
    router.events.on('routeChangeComplete', handleStop);
    router.events.on('routeChangeError', handleStop);

    return () => {
      router.events.off('routeChangeStart', handleStart);
      router.events.off('routeChangeComplete', handleStop);
      router.events.off('routeChangeError', handleStop);
    };
  }, [router]);

  useEffect(() => {
    document.cookie = `arco-lang=${lang}; path=/`;
    document.cookie = `arco-theme=${theme}; path=/`;
    changeTheme(theme);
  }, [lang, theme]);

  const contextValue = {
    lang,
    setLang,
    theme,
    setTheme
  };

  return (
    <>
      <Head>
        <title>工业软件组件化构建开发与运行支撑环境</title>
        <link
          rel="shortcut icon"
          type="image/x-icon"
          href="https://unpkg.byted-static.com/latest/byted/arco-config/assets/favicon.ico"
        />
      </Head>
      <ConfigProvider
        locale={locale}
        componentConfig={{
          Card: {
            bordered: false
          },
          List: {
            bordered: false
          },
          Table: {
            border: false
          }
        }}
      >
        <Provider store={store}>
          <GlobalContext.Provider value={contextValue}>
            {Component.displayName === 'LoginPage' ? (
              <Component {...pageProps} suppressHydrationWarning />
            ) : (
              <Layout>
                <Component {...pageProps} suppressHydrationWarning />
              </Layout>
            )}
          </GlobalContext.Provider>
        </Provider>
      </ConfigProvider>
    </>

  );
}

// fix: next build ssr can't attach the localstorage
MyApp.getInitialProps = async (appContext) => {
  const { ctx } = appContext;
  const serverCookies = cookies(ctx);
  return {
    renderConfig: {
      arcoLang: serverCookies['arco-lang'],
      arcoTheme: serverCookies['arco-theme']
    }
  };
};
