import { type ReactNode, useMemo } from 'react';

import { ThemeProvider } from '@material-hu/mui/styles';
import { createHuGoTheme } from '@material-hu/theme/hugo';

import { DialogLayerProvider } from '@material-hu/components/layers/Dialogs';
import { DrawerLayerProvider } from '@material-hu/components/layers/Drawers';
import { MenuLayerProvider } from '@material-hu/components/layers/Menus';

import { isProd, THEMES } from 'src/constants';

type StoredSettings = {
  theme?: string;
};

const isObject = (value: unknown): value is Record<string, unknown> =>
  typeof value === 'object' && value !== null;

// HACK - REMOVE WHEN TESTING IS DONE: Workaround to test dark mode
// It gets the theme mode from the stored settings in local storage
export const getStoredThemeMode = () => {
  if (isProd) {
    return undefined;
  }

  const storedSettings = window.localStorage.getItem('settings');
  if (!storedSettings) {
    return undefined;
  }

  try {
    const parsedSettings: unknown = JSON.parse(storedSettings);
    if (!isObject(parsedSettings)) {
      return undefined;
    }

    const { theme } = parsedSettings as StoredSettings;
    if (!theme) {
      return undefined;
    }

    if (theme === THEMES.DARK) {
      return 'dark';
    }

    if (theme === THEMES.LIGHT) {
      return 'light';
    }

    return undefined;
  } catch {
    return undefined;
  }
};

const useHuGoTheme = () => {
  // useMemo is needed to stop the theme from being recreated on every render
  return useMemo(() => {
    const mode = getStoredThemeMode();
    const newTheme = createHuGoTheme(mode ? { mode } : undefined);

    const HuGoThemeProvider = ({ children }: { children: ReactNode }) => (
      <ThemeProvider theme={newTheme}>
        <MenuLayerProvider>
          <DialogLayerProvider>
            <DrawerLayerProvider>{children}</DrawerLayerProvider>
          </DialogLayerProvider>
        </MenuLayerProvider>
      </ThemeProvider>
    );

    HuGoThemeProvider.displayName = 'HuGoThemeProvider';

    return HuGoThemeProvider;
  }, []);
};

export const withHuGoTheme = <P extends object>(
  Component: React.ComponentType<P>,
) => {
  const Wrapped = (props: P) => {
    const HuGoThemeProvider = useHuGoTheme();
    return (
      <HuGoThemeProvider>
        <Component {...props} />
      </HuGoThemeProvider>
    );
  };
  Wrapped.displayName = `withHuGoTheme(${Component.displayName ?? Component.name ?? 'Component'})`;
  return Wrapped;
};

export default useHuGoTheme;
