import type { AppTheme, AppUser } from './utils/types';
import type { DRootProps } from '@react-devui/ui';
import type { DLang } from '@react-devui/ui/utils/types';

import { isNull } from 'lodash';
import { useStore } from 'rcl-store';
import React, { useEffect, useMemo, useState } from 'react';

import { useAsync, useMount, useStorage } from '@react-devui/hooks';
import { DNotification, DToast } from '@react-devui/ui';
import { DRoot } from '@react-devui/ui';

import AppRoutes from './Routes';
import { STORAGE_KEY } from './config/storage';
import { GlobalStore, TOKEN, useHttp, useInit } from './core';

function App() {
  const http = useHttp();
  const init = useInit();
  const async = useAsync();
  const languageStorage = useStorage<DLang>(...STORAGE_KEY.language);
  const themeStorage = useStorage<AppTheme>(...STORAGE_KEY.theme);
  const [loading, setLoading] = useState(!isNull(TOKEN.value));
  const [{ dialogs, notifications, toasts }] = useStore(GlobalStore, ['dialogs', 'notifications', 'toasts']);

  useMount(() => {
    if (!isNull(TOKEN.value)) {
      http<string>({
        url: '/auth/refresh',
        method: 'post',
      }).subscribe({
        next: (res) => {
          TOKEN.set(res);

          http<AppUser>({
            url: '/auth/me',
            method: 'get',
          }).subscribe({
            next: (res) => {
              setLoading(false);
              init(res);
            },
            error: () => {
              setLoading(false);
            },
          });
        },
        error: () => {
          setLoading(false);
        },
      });
    }
  });

  useEffect(() => {
    if (loading === false) {
      const loader = document.querySelector('.fp-loader') as HTMLElement;
      loader.style.cssText = 'opacity:0;transition:opacity 0.5s ease-out;';
      async.setTimeout(() => {
        document.body.removeChild(loader);
      }, 500);
    }
  }, [async, loading]);

  useEffect(() => {
    document.documentElement.lang = languageStorage.value;
  }, [languageStorage.value]);

  useEffect(() => {
    for (const t of ['light', 'dark']) {
      document.body.classList.toggle(t, themeStorage.value === t);
    }
    const colorScheme = document.documentElement.style.colorScheme;
    document.documentElement.style.colorScheme = themeStorage.value;
    return () => {
      document.documentElement.style.colorScheme = colorScheme;
    };
  }, [themeStorage.value]);

  const rootContext = useMemo<DRootProps['context']>(
    () => ({
      i18n: { lang: languageStorage.value },
      layout: { pageScrollEl: '#app-main', contentResizeEl: '#app-content' },
    }),
    [languageStorage.value]
  );

  return (
    <DRoot context={rootContext}>
      {loading ? null : <AppRoutes />}
      {dialogs.map(({ key, type, props }) => React.createElement(type, { key, ...props }))}
      {notifications.map(({ key, ...props }) => (
        <DNotification {...props} key={key}></DNotification>
      ))}
      {toasts.map(({ key, ...props }) => (
        <DToast {...props} key={key}></DToast>
      ))}
    </DRoot>
  );
}

export default App;