import { PropsWithChildren, useContext, useEffect, useMemo } from 'react';

import { ThemedChildren } from './ThemedChildren';
import type { Theming } from './const';
import { DEFAULT_BASE_THEME, DEFAULT_SCREEN_MODE } from './const';
import { getThemeClassName } from './helpers';
import { ThemeContext } from './ThemeProviderContext';

type ThemeProviderProps = PropsWithChildren<Theming> & { className?: string };

// RegEx to check for `np-theme-` class name
const themeClass = /\bnp-theme-[a-z-]+\b/g;

export const ThemeProvider = ({
  theme = DEFAULT_BASE_THEME,
  screenMode = DEFAULT_SCREEN_MODE,
  isNotRootProvider = false,
  children,
  className = undefined,
}: ThemeProviderProps) => {
  const isContextRoot = useContext(ThemeContext) === undefined;

  // useEffect hook used to apply the theme class to the HTML element
  useEffect(() => {
    if (!isNotRootProvider && isContextRoot) {
      // Remove all the theme classes from the documentElement
      document.documentElement.className.match(themeClass)?.forEach((item) => {
        document.documentElement.classList.remove(item);
      });
      getThemeClassName(theme, screenMode)
        .split(' ')
        .forEach((item) => {
          document.documentElement.classList.add(item);
        });
    }
  }, [isNotRootProvider, isContextRoot, theme, screenMode]);

  const contextValue = useMemo(() => ({ theme, screenMode }), [screenMode, theme]);

  return (
    <ThemeContext.Provider value={contextValue}>
      <ThemedChildren className={className}>{children}</ThemedChildren>
    </ThemeContext.Provider>
  );
};
