import { useLocalStorage } from '@/hooks';
import { PropsWithChildren, createContext, useContext } from 'react';

type ThemeMode = 'light' | 'dark' | 'auto';
type ThemeOrientation = 'vertical' | 'horizontal';

type ThemeDirection = 'ltr' | 'rtl';

type ThemePresetColor =
  | 'default'
  | 'theme1'
  | 'theme2'
  | 'theme3'
  | 'theme4'
  | 'theme5'
  | 'theme6'
  | 'theme7'
  | 'theme8';

type ThemeFontFamily =
  | `'Inter', sans-serif`
  | `'Poppins', sans-serif`
  | `'Roboto', sans-serif`
  | `'Public Sans', sans-serif`
  | /** Any font family name as string */ string;

type ThemeConfig = {
  /**
   * Default font family for the application.
   * @example
   * fontFamily: `'Inter', sans-serif`
   */
  fontFamily: ThemeFontFamily;

  /**
   * Layout orientation: 'vertical' or 'horizontal'.
   * @example
   * themeOrientation: 'vertical'
   */
  themeOrientation: ThemeOrientation;

  /**
   * Enables/disables mini mode for the drawer.
   * @example
   * miniDrawer: false
   */
  miniDrawer: boolean;

  /**
   * If true, the main layout is wrapped in a centered container.
   * @example
   * container: true
   */
  container: boolean;

  /**
   * Theme mode: 'light', 'dark', or 'auto'.
   * @example
   * mode: 'light'
   */
  mode: ThemeMode;

  /**
   * Default theme color preset.
   * @example
   * presetColor: 'theme4'
   */
  presetColor: ThemePresetColor;

  /**
   * Text direction: 'ltr' (left-to-right) or 'rtl' (right-to-left).
   * @example
   * themeDirection: 'ltr'
   */
  themeDirection: ThemeDirection;

  /**
   * Default application path.
   * @example
   * appDefaultPath: '/dashboard'
   */
  appDefaultPath: string;

  /**
   * Width of the side drawer in pixels.
   * @example
   * drawerWidth: 260
   */
  drawerWidth: number;

  /**
   * Maximum number of items shown horizontally in the menu.
   * @example
   * horizontalMaxItems: 6
   */
  horizontalMaxItems: number;

  /**
   * Base spacing for the layout (MUI units).
   * @example
   * spacing: 2
   */
  spacing: number;

  setFontFamily: (fontFamily: ThemeFontFamily) => void;
  setThemeOrientation: (themeOrientation: ThemeOrientation) => void;
  setMiniDrawer: (miniDrawer: boolean) => void;
  setContainer: (container: boolean) => void;
  setMode: (mode: ThemeMode) => void;
  setPresetColor: (presetColor: ThemePresetColor) => void;
  setThemeDirection: (themeDirection: ThemeDirection) => void;
  setAppDefaultPath: (appDefaultPath: string) => void;
  setDrawerWidth: (drawerWidth: number) => void;
  setHorizontalMaxItems: (horizontalMaxItems: number) => void;
  isVerticalLayout: (orientation: ThemeOrientation) => boolean;
  isHorizontalLayout: (orientation: ThemeOrientation) => boolean;
};

type ThemeProvierProps = PropsWithChildren<{ initialConfig: ThemeConfig }>;

function notImplemented(): void {
  throw new Error('Method must be implemented');
}

const initialState: ThemeConfig = {
  fontFamily: `'Inter', sans-serif`,
  themeOrientation: 'vertical',
  miniDrawer: false,
  container: false,
  mode: 'light',
  presetColor: 'theme4',
  themeDirection: 'ltr',
  appDefaultPath: '/',
  drawerWidth: 260,
  horizontalMaxItems: 6,
  spacing: 2,

  setFontFamily: notImplemented,
  setThemeOrientation: notImplemented,
  setMiniDrawer: notImplemented,
  setContainer: notImplemented,
  setMode: notImplemented,
  setPresetColor: notImplemented,
  setThemeDirection: notImplemented,
  setAppDefaultPath: notImplemented,
  setDrawerWidth: notImplemented,
  setHorizontalMaxItems: notImplemented,
  isVerticalLayout: (_) => false,
  isHorizontalLayout: (_) => false
};

function isVerticalLayout(layout: ThemeOrientation) {
  return layout === ('vertical' as ThemeOrientation);
}
function isHorizontalLayout(layout: ThemeOrientation) {
  return layout === ('horizontal' as ThemeOrientation);
}

const ThemeContext = createContext(initialState);

function ThemeProvider({ initialConfig, children }: ThemeProvierProps): JSX.Element {
  const [config, setConfig] = useLocalStorage('theme-config', { ...initialState, ...initialConfig });
  function setFontFamily(fontFamily: ThemeFontFamily) {
    setConfig((config: ThemeConfig) => ({ ...config, fontFamily }));
  }
  function setThemeOrientation(themeOrientation: ThemeOrientation) {
    setConfig((config: ThemeConfig) => ({ ...config, themeOrientation }));
  }
  function setMiniDrawer(miniDrawer: boolean) {
    setConfig((config: ThemeConfig) => ({ ...config, miniDrawer }));
  }
  function setContainer(container: boolean) {
    setConfig((config: ThemeConfig) => ({ ...config, container }));
  }
  function setMode(mode: ThemeMode) {
    setConfig((config: ThemeConfig) => ({ ...config, mode }));
  }
  function setPresetColor(presetColor: ThemePresetColor) {
    setConfig((config: ThemeConfig) => ({ ...config, presetColor }));
  }
  function setThemeDirection(themeDirection: ThemeDirection) {
    setConfig((config: ThemeConfig) => ({ ...config, themeDirection }));
  }
  function setAppDefaultPath(appDefaultPath: string) {
    setConfig((config: ThemeConfig) => ({ ...config, appDefaultPath }));
  }
  function setDrawerWidth(drawerWidth: number) {
    setConfig((config: ThemeConfig) => ({ ...config, drawerWidth }));
  }
  function setHorizontalMaxItems(horizontalMaxItems: number) {
    setConfig((config: ThemeConfig) => ({ ...config, horizontalMaxItems }));
  }
  return (
    <ThemeContext.Provider
      value={{
        ...(config as ThemeConfig),

        setFontFamily,
        setThemeOrientation,
        setMiniDrawer,
        setContainer,
        setMode,
        setPresetColor,
        setThemeDirection,
        setAppDefaultPath,
        setDrawerWidth,
        setHorizontalMaxItems,

        isVerticalLayout,
        isHorizontalLayout
      }}
    >
      {children}
    </ThemeContext.Provider>
  );
}

function useThemeContext(): ThemeConfig {
  return useContext(ThemeContext);
}

function useThemeConfig(): ThemeConfig {
  return useThemeContext();
}

export type { ThemeConfig, ThemeDirection, ThemeFontFamily, ThemeMode, ThemeOrientation, ThemePresetColor };
export { ThemeContext, ThemeProvider, useThemeConfig, useThemeContext };
