import { FC, useReducer } from 'react'
import { ThemeProvider } from 'styled-components'

import PopoverStyle from '../../popover/globalStyle'
import { Portal } from '../../portal'
import defaultTheme, { VuiTheme } from '../../theme'
import { Toaster } from '../../toast'
import { ToastListItem } from '../../toast/toast.types'
import { ChildrenProp } from '../types'
import { VuiContextProvider } from './context'
import GlobalStyle from './globalStyle'
import NotifyOffline from './notifyOffline'
import { genericReducer, toastsReducer } from './reducers'
import ResetCSS from './resetCSS'

type VuiProviderProps = {
  /** Adds basic styles to body @default true */
  globalStyle?: boolean
  /** Applies custom CSS reset @default true */
  resetCSS?: boolean
  /** Modified theme config using 'extendTheme' utility */
  theme?: VuiTheme
  /** Enables displaying offline/online toast notifications @default false */
  notifyOffline?: boolean
}

/** Provides theme to all wrapped components and by default includes CSS reset and global styles. */
const VuiProvider: FC<VuiProviderProps & ChildrenProp> = ({
  children,
  globalStyle = true,
  resetCSS = true,
  theme = defaultTheme as VuiTheme,
  notifyOffline = false,
}) => {
  const [toasts, toastsDispatch] = useReducer(toastsReducer, { list: [] })
  const [portalSlot, setPortalSlot] = useReducer(genericReducer, null)

  const addToast = (toast: ToastListItem) => toastsDispatch({ type: 'add', toast })
  const removeToast = (id: string) => toastsDispatch({ type: 'remove', toast: { id } })

  const context = { toasts, addToast, removeToast, setPortalSlot }

  return (
    <VuiContextProvider value={context}>
      <ThemeProvider theme={theme}>
        <>
          {resetCSS && <ResetCSS />}
          <GlobalStyle globalStyle={globalStyle} />
          <PopoverStyle />
          {children}
          {notifyOffline && <NotifyOffline />}
          <Portal>
            {portalSlot}
            <Toaster />
          </Portal>
        </>
      </ThemeProvider>
    </VuiContextProvider>
  )
}

export default VuiProvider
