import type React from 'react';

import CloseIcon from '@mui/icons-material/Close';
import {
  Badge,
  Box,
  Button,
  IconButton,
  LinearProgress,
  SnackbarContent,
  Stack,
  Typography,
  useTheme,
} from '@mui/material';
import { keyframes } from '@mui/system';
import {
  IconAlertTriangle,
  IconCheck,
  IconInfoCircle,
  IconX,
} from '@tabler/icons-react';
import {
  type SnackbarKey,
  SnackbarProvider,
  useSnackbar as useNotistackSnackbar,
} from 'notistack';

import { type SnackbarProps } from './types';

const SNACKBAR_DURATIONS = {
  withAction: {
    extra: 2000, // Additional time when there's a cancel action
  },
} as const;

const NOTISTACK_QUERY = '.notistack-SnackbarContainer';
const PADDING = 8;

export const useSnackbar = () => {
  const { enqueueSnackbar: enqueueNotistackSnackbar, closeSnackbar } =
    useNotistackSnackbar();
  const theme = useTheme();
  const backgroundColor = theme.palette.new.background.elements.inverted;

  const getProps = (
    variant: string,
  ): {
    Icon: React.ElementType;
    color: string;
    iconColor: string | undefined;
  } => {
    switch (variant) {
      case 'warning':
        return {
          Icon: IconAlertTriangle,
          color: theme.palette.new.border.states.warning,
          iconColor:
            theme.palette.newBase?.yellow[600] ?? theme.palette.warning.main,
        };
      case 'info':
        return {
          Icon: IconInfoCircle,
          color: theme.palette.new.border.states.info,
          iconColor:
            theme.palette.newBase?.skyBlue[600] ?? theme.palette.info.main,
        };
      case 'error':
        return {
          Icon: IconX,
          color: theme.palette.new.border.states.error,
          iconColor:
            theme.palette.newBase?.red[600] ?? theme.palette.error.main,
        };
      default:
      case 'success':
        return {
          Icon: IconCheck,
          color: theme.palette.new.border.states.success,
          iconColor:
            theme.palette.newBase?.green[600] ?? theme.palette.success.main,
        };
    }
  };

  const globalXSBase = {
    fontFamily: 'Roboto',
    lineHeight: '140%',
    fontWeight: 400,
    letterSpacing: 0.2,
    fontSize: 14,
  };

  const enqueueSnackbar = (props: SnackbarProps) => {
    const {
      title,
      description,
      hasClose = true,
      cancelAction,
      variant,
      spacing,
      autoHideDuration = 6000,
      onClose,
    } = props;
    const { Icon, color, iconColor } = getProps(variant);
    const progressAnimation = keyframes`from { width: 0%; } to { width: 100%; }`;
    const progressDuration = autoHideDuration * 0.8;
    const durations = {
      hide: cancelAction
        ? autoHideDuration + SNACKBAR_DURATIONS.withAction.extra
        : autoHideDuration,
      progress: cancelAction
        ? progressDuration + SNACKBAR_DURATIONS.withAction.extra
        : progressDuration,
    };

    return enqueueNotistackSnackbar('', {
      autoHideDuration: durations.hide,
      anchorOrigin: { vertical: 'bottom', horizontal: 'center' },
      onClose,
      onEnter: () => {
        const snackbarElement: HTMLElement | null =
          document.querySelector(NOTISTACK_QUERY);

        if (snackbarElement) {
          if (spacing?.bottom) {
            const newBottom = spacing?.bottom + PADDING;
            snackbarElement.style.bottom = `${newBottom}px`;
          }
          if (spacing?.top) {
            const newTop = spacing?.top + PADDING;
            snackbarElement.style.top = `${newTop}px`;
          }
          if (spacing?.left) {
            const newLeft = spacing?.left + PADDING;
            snackbarElement.style.left = `${newLeft}px`;
          }
          if (spacing?.right) {
            const newRight = spacing?.right + PADDING;
            snackbarElement.style.right = `${newRight}px`;
          }
        }
      },
      content: key => (
        <div
          style={{
            borderRadius: '8px',
            overflow: 'hidden',
            width: 600,
            maxWidth: '100%',
            position: 'relative',
          }}
        >
          <SnackbarContent
            key={key}
            style={{
              backgroundColor: backgroundColor,
              display: 'flex',
              borderRadius: 0,
            }}
            message={
              <Stack
                sx={{
                  flexDirection: 'row',
                  alignItems: 'center',
                  gap: 1,
                  ml: 1,
                  maxWidth: cancelAction ? 400 : '99%',
                }}
              >
                <Badge
                  badgeContent={
                    <Box
                      sx={{
                        width: 16,
                        height: 16,
                        display: 'flex',
                        alignItems: 'center',
                      }}
                    >
                      <Icon />
                    </Box>
                  }
                  overlap="circular"
                  sx={{
                    mr: 2,
                    mb: title && description ? 2 : 0,
                    '.MuiBadge-badge': {
                      backgroundColor: iconColor,
                      minWidth: 24,
                      minHeight: 24,
                      borderRadius: '50%',
                      padding: 0,
                    },
                  }}
                />
                <Stack>
                  {title && (
                    <Typography
                      sx={{
                        // Temporally use manual style for -> globalS
                        ...globalXSBase,
                        fontSize: 16,
                        fontWeight: 500,
                        color: theme.palette.new.text.neutral.inverted,
                      }}
                    >
                      {title}
                    </Typography>
                  )}
                  {description && (
                    <Typography
                      sx={{
                        // Temporally use manual style for -> globalXS
                        ...globalXSBase,
                        color: theme.palette.new.text.neutral.inverted,
                      }}
                    >
                      {description}
                    </Typography>
                  )}
                </Stack>
              </Stack>
            }
            action={[
              cancelAction && (
                <Button
                  key="cancelButton"
                  onClick={() => {
                    cancelAction?.onClick();
                    closeSnackbar(key);
                  }}
                  sx={{
                    p: 0.5,
                    mr: 4,
                    color: theme.palette.new.text.neutral.inverted,
                    minWidth: 'auto',
                    maxWidth: 120,
                  }}
                >
                  <Typography
                    variant="globalS"
                    fontWeight="fontWeightRegular"
                    sx={{
                      textDecoration: 'underline',
                      textTransform: 'none',
                      color: theme.palette.new.text.neutral.inverted,
                    }}
                  >
                    {cancelAction.text}
                  </Typography>
                </Button>
              ),
              hasClose && (
                <IconButton
                  key="closeButton"
                  onClick={() => closeSnackbar(key)}
                  sx={{
                    p: 0,
                    top: 12,
                    right: 12,
                    fontSize: '12px',
                    position: 'absolute',
                    color: theme.palette.new.text.neutral.inverted,
                  }}
                >
                  <CloseIcon
                    sx={{ fontSize: '16px' }}
                    color="inherit"
                  />
                </IconButton>
              ),
            ]}
          />
          <LinearProgress
            variant="determinate"
            value={100}
            sx={{
              height: '6px',
              backgroundColor: color,
              '& .MuiLinearProgress-bar': {
                backgroundColor: iconColor,
                animation: `${progressAnimation} ${durations.progress / 1000}s linear`,
              },
            }}
          />
        </div>
      ),
    });
  };

  return { enqueueSnackbar, closeSnackbar };
};

export type { SnackbarProps, SnackbarKey };
export { SnackbarProvider };

export default useSnackbar;
