import type { LayoutType } from '@/@types/theme'
import AppRoute from '@/components/route/AppRoute'
import PermissionGuard from '@/components/route/PermissionGuard'
import ProtectedRoute from '@/components/route/ProtectedRoute'
import PublicRoute from '@/components/route/PublicRoute'
import Loading from '@/components/shared/Loading'
import PageContainer from '@/components/template/PageContainer'
import { Alert, Button } from '@/components/ui'
import appConfig from '@/configs/app.config'
import { protectedRoutes, publicRoutes } from '@/configs/routes.config'
import { store, useStoreState } from '@/store'
import { Suspense, useEffect } from 'react'
import { ErrorBoundary } from 'react-error-boundary'
import { MdArrowBack } from 'react-icons/md'
import { Navigate, Route, Routes, useLocation } from 'react-router-dom'
import DialogProvider from './shared/DialogContext'
import DialogShowComponent from './shared/DialogContext/DialogShowComponent'
import UiDialog from './shared/UiDialog'

interface ViewsProps {
  pageContainerType?: 'default' | 'gutterless' | 'contained'
  layout?: LayoutType
}

type AllRoutesProps = ViewsProps

const { authenticatedEntryPath } = appConfig

const AllRoutes = (props: AllRoutesProps) => {
  return (
    <Routes>
      <Route path="/" element={<ProtectedRoute />}>
        <Route path="/" element={<Navigate replace to={authenticatedEntryPath} />} />
        {protectedRoutes.map((route, index) => (
          <Route
            key={route.key + index}
            path={route.path}
            element={
              <PermissionGuard permissions={route.authority}>
                <PageContainer {...props} {...route.meta}>
                  <AppRoute routeKey={route.key} component={route.component} {...route.meta} />
                </PageContainer>
              </PermissionGuard>
            }
          />
        ))}
        <Route path="*" element={<Navigate replace to="/" />} />
      </Route>
      <Route path="/" element={<PublicRoute />}>
        {publicRoutes.map((route) => (
          <Route
            key={route.path}
            path={route.path}
            element={<AppRoute routeKey={route.key} component={route.component} {...route.meta} />}
          />
        ))}
      </Route>
    </Routes>
  )
}

function fallbackRender({ error, resetErrorBoundary }: { error: Error; resetErrorBoundary: any }) {
  return (
    <Alert showIcon className="mb-4" type="danger">
      <h5>{error.name ?? 'Hata!'}</h5>
      <div>{error.message}</div>
      <Button size="xs" className="mt-2" variant="default" onClick={resetErrorBoundary}>
        <MdArrowBack />
      </Button>
    </Alert>
  )
}

const Views = (props: ViewsProps) => {
  const { setWarning, removeError } = store.getActions().base.messages
  const { errors, warning } = useStoreState((state) => state.base.messages)
  const location = useLocation()

  useEffect(() => {
    setWarning('')
  }, [location, setWarning])

  return (
    <ErrorBoundary fallbackRender={fallbackRender}>
      <Suspense fallback={<Loading loading={true} />}>
        {!!warning?.length && (
          <Alert showIcon className="mb-4" type="warning">
            {warning.map((w, i) => (
              <div key={i}>{w}</div>
            ))}
          </Alert>
        )}
        {errors?.map((e) => (
          <UiDialog
            key={e.id}
            isOpen={true}
            type={'danger'}
            onConfirm={() => {
              removeError(e.id)
            }}
            onClose={() => {
              removeError(e.id)
            }}
            title={e.title}
          >
            {e.message}
            <p>{e.statusCode}</p>
            <small className="italic">{e.cid}</small>
          </UiDialog>
        ))}
        <DialogProvider>
          <DialogShowComponent></DialogShowComponent>
          <AllRoutes {...props} />
        </DialogProvider>
      </Suspense>
    </ErrorBoundary>
  )
}

export default Views
