import { Alert, AlertTitle, Box, Typography, type AlertProps } from '@mui/material';
import { ReactNode } from 'react';
import { useRouteError } from 'react-router-dom';

import Button from '../Button';

interface InternalErrorFallbackProps {
  title?: string;
  desc: string;
  extraContent?: ReactNode;
  severity?: AlertProps['severity'];
}

function InternalErrorFallback({
  title = 'Something went wrong...',
  desc,
  extraContent = null,
  severity = 'error',
}: InternalErrorFallbackProps) {
  const gotoHome = () => window.location.replace('/');
  const refresh = () => window.location.reload();

  return (
    <Alert
      severity={severity}
      variant="outlined"
      icon={false}
      sx={{
        justifyContent: 'center',
      }}>
      {title ? <AlertTitle>{title}</AlertTitle> : null}
      {desc ? (
        <Typography
          variant="body2"
          sx={{
            mb: 1,
          }}>
          {desc}
        </Typography>
      ) : null}
      {extraContent ?? (
        <Box sx={{ display: 'flex', gap: 1, justifyContent: 'center', alignItems: 'center' }}>
          <Button variant="outlined" color={severity} size="small" onClick={gotoHome}>
            Home
          </Button>

          <Button variant="contained" color={severity} size="small" onClick={refresh}>
            Refresh
          </Button>
        </Box>
      )}
    </Alert>
  );
}

export interface ErrorFallbackProps {
  error: Error;
}

export function ErrorFallback({ error }: ErrorFallbackProps) {
  return <InternalErrorFallback desc={error.message} />;
}

export interface ErrorFallbackRetryProps {
  error: Error;
  resetErrorBoundary: () => void;
}

export function ErrorFallbackRetry({ error, resetErrorBoundary }: ErrorFallbackRetryProps) {
  return (
    <InternalErrorFallback
      desc={error.message}
      extraContent={
        <Button variant="contained" color="error" size="small" onClick={resetErrorBoundary}>
          Try again
        </Button>
      }
    />
  );
}

export function ReactRouterErrorFallback() {
  const error = useRouteError() as Error;
  return <InternalErrorFallback title="Current route occurred an error" desc={error.message} />;
}
