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';
import { getMyComponents, getPubComponents, getTeamComponents } from '@/api/components';
import { getPubFlowList, getMyFlowList } from '@/api/flow';
import dayjs from 'dayjs';


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 } }));
    getComponentData();
  }

  const getComponentData = async () => {
    try {
      const requests = [
        { promise: getMyComponents(), key: 'myLibs' },
        { promise: getPubComponents(), key: 'pubLibs' },
        { promise: getTeamComponents(), key: 'teamLibs' },
        {
          promise: getPubFlowList({
            currPage: 1,
            pageSize: 999
          }),
          key: 'pubFlow'
        },
        {
          promise: getMyFlowList({
            currPage: 1,
            pageSize: 999
          }),
          key: 'myFlow'
        }
        // {promise: getEventList(), key: 'eventList'}
      ];

      const obj: any = {
        myLibs: null,
        pubLibs: null,
        teamLibs: null,
        pubFlow: null,
        myFlow: null,
        updateTime: dayjs().format('YYYY-MM-DD HH:mm:ss')
      };

      const userInfo = JSON.parse(sessionStorage.getItem('userInfo') || '{}');

      // 分别处理每个请求
      for (const { promise, key } of requests) {
        try {
          const res: any = await promise;
          if (res?.code === 200) {
            if (key === 'pubFlow' || key === 'myFlow') {
              res?.data.list.forEach(item => {
                item['fontCompType'] = 'complex';
              });
              // 更新本地存储数据
              obj[key] = res?.data.list || null;
            }
            // 给协同组件添加一个后续处理数据时使用的类型
            else if (key === 'teamLibs') {
              res.data.forEach(item => {
                item.children.forEach(v => {
                  v['fontCompType'] = 'team';
                });
              });
              obj[key] = res?.data || null;
            }
            else {
              // 更新本地存储数据
              res.data.forEach(item => {
                item.children.forEach(v => {
                  v['fontCompType'] = 'normal';
                });
              });
              obj[key] = res?.data || null;
            }
          }
          sessionStorage.setItem(`compLibs${userInfo.userId}`, JSON.stringify(obj));
        } catch (error) {
          console.error(`加载${key}失败:`, error);
        }
      }
    } catch (error) {
      console.error('加载组件库失败:', error);
    }
  };

  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']
    }
  };
};
