import {
  AppProps,
  ErrorBoundary,
  ErrorComponent,
  ErrorFallbackProps,
  useQueryErrorResetBoundary,
} from "blitz"

import CssBaseline from "@mui/material/CssBaseline";
import { ThemeProvider } from "@mui/material/styles";
import React, { useEffect, useMemo, useState } from "react";
import { useGlobalState } from "app/core/state/GlobalState";
import { LocalStorageKeys } from "app/core/dto/SaveKeys";
import { ThemeMode } from "app/core/state/ThemeMode";
import { darkPalette } from "app/core/theme/darkTheme";
import { lightPalette } from "app/core/theme/lightTheme";
import { getTheme } from "app/core/theme/Theme";
import { useTheme } from "next-themes";

const App = ({ Component, pageProps }: AppProps)  => {
  const [mounted, setMounted] = useState(false)
  const {theme: prefersDarkMode} = useTheme()
  const [preferedColorScheme ,setPreferedColorScheme] = useGlobalState(state => [state.preferedColorScheme, state.setPreferedColorScheme])
  const reset = useQueryErrorResetBoundary().reset

  useEffect(() => {
      const localPreferedTheme = localStorage.getItem(LocalStorageKeys.PREFERED_COLOR_SCHEME);
      if (localPreferedTheme) {
          setPreferedColorScheme(localPreferedTheme as ThemeMode)
          return
      }

      const preferedTheme = prefersDarkMode ? ThemeMode.DARK_MODE : ThemeMode.LIGHT_MODE;
      setPreferedColorScheme(preferedTheme)
      // eslint-disable-next-line
  }, [prefersDarkMode]) // Need to be only used on prefersDarkMode change
  const getLayout = Component.getLayout || ((page) => page)

  const palette = useMemo(
    ()=> getTheme(preferedColorScheme === ThemeMode.DARK_MODE ? darkPalette.palette : lightPalette.palette),
    [preferedColorScheme]);

  useEffect(() => setMounted(true), [])
  if (!mounted) return null

  return (
    <ThemeProvider theme={palette}>
      <CssBaseline />
      <ErrorBoundary
        FallbackComponent={RootErrorFallback}
        onReset={reset}
      >
        {getLayout(<Component {...pageProps} />)}
      </ErrorBoundary>
    </ThemeProvider>
  );
}

function RootErrorFallback({ error }: ErrorFallbackProps) {
  return <ErrorComponent statusCode={error.statusCode || 400} title={error.message || error.name} />
}

export default App;