import { FC, useState } from 'react';
import { useMutation } from 'react-query';
import { matchPath, useLocation, useNavigate } from 'react-router-dom';

import {
  IconArchive,
  IconArrowsRightLeft,
  IconPinned,
  IconPinnedOff,
} from '@material-hu/icons/tabler';
import Stack from '@material-hu/mui/Stack';
import { useTheme } from '@material-hu/mui/styles';

import HuMenuList from '@material-hu/components/composed-components/MenuList';
import HuBadge from '@material-hu/components/design-system/Badge';
import HuListItem from '@material-hu/components/design-system/List/components/ListItem';

import { linkIcon } from 'src/constants/widgets';
import useHuGoTheme from 'src/hooks/useHuGoTheme';
import {
  groupsKeys,
  invalidateGroupList,
  removePinnedGroup,
  removeUnpinnedGroup,
} from 'src/pages/dashboard/groups/queries';
import { groupsRoutes } from 'src/pages/dashboard/groups/routes';
import { pinGroup, unpinGroup } from 'src/services/groups';
import { Icon } from 'src/types/icons';
import { insertIf } from 'src/utils/arrays';
import { useLokaliseTranslation } from 'src/utils/i18n';
import { optimisticUpdate } from 'src/utils/queries';

export type NavGroupItemProps = {
  id: number;
  title: string;
  icon?: Icon;
  onClick?: () => void;
  unreadCount: number;
  isPinned?: boolean;
  isArchived?: boolean;
  isMultiCompany?: boolean;
};

const NavGroupItem: FC<NavGroupItemProps> = props => {
  const {
    id,
    title,
    icon = linkIcon,
    onClick,
    unreadCount,
    isPinned,
    isArchived,
    isMultiCompany,
  } = props;
  const HugoProvider = useHuGoTheme();
  const navigate = useNavigate();
  const { t } = useLokaliseTranslation('group');
  const theme = useTheme();
  const [isHovered, setIsHovered] = useState(false);

  const { mutate: pin } = useMutation(pinGroup, {
    onSettled: () => {
      invalidateGroupList();
    },
    onMutate: () => {
      optimisticUpdate(id, groupsKeys.allUnpinnedList(), removeUnpinnedGroup);
    },
  });

  const { mutate: unpin } = useMutation(unpinGroup, {
    onSettled: () => {
      invalidateGroupList();
    },
    onMutate: () => {
      optimisticUpdate(id, groupsKeys.allPinnedList(), removePinnedGroup);
    },
  });

  const location = useLocation();

  const PATH = groupsRoutes.detail(id);

  const exactMatch = !!matchPath(
    {
      path: PATH,
      end: false,
    },
    location.pathname,
  );

  const togglePin = () => {
    if (isPinned) {
      unpin(id);
    } else {
      pin(id);
    }
  };

  const handleClick = () => {
    onClick?.();
    if (PATH) {
      navigate(PATH);
    }
  };

  return (
    <HugoProvider>
      <Stack
        direction="row"
        alignItems="center"
        onMouseEnter={e => {
          setTimeout(() => {
            // onMouseLeave event is not triggered when the mouse is too fast, so we need to use setTimeout to check if the mouse is still hovering
            if (e.target instanceof Element && e.target.matches(':hover')) {
              setIsHovered(true);
            }
          }, 50);
        }}
        onMouseLeave={() => {
          setIsHovered(false);
        }}
      >
        <HuListItem
          avatar={{
            src: icon.value,
            alt: title,
          }}
          selected={exactMatch}
          text={{
            title: (
              <Stack
                direction="row"
                spacing={1}
                alignItems="center"
                sx={{ mr: unreadCount ? 2 : 0 }}
              >
                <span>{title}</span>
                {isArchived && (
                  <Stack
                    sx={{
                      color: th => th.palette.new.text.feedback.warning,
                    }}
                  >
                    <IconArchive size={16} />
                  </Stack>
                )}
                {isMultiCompany && (
                  <Stack>
                    <IconArrowsRightLeft size={16} />
                  </Stack>
                )}
              </Stack>
            ),
          }}
          sideContent={
            unreadCount > 0 && (
              <HuBadge
                color="primary"
                badgeContent={unreadCount}
                sx={{ mr: 1 }}
              />
            )
          }
          onClick={handleClick}
          actionMenuList={
            isPinned !== undefined &&
            isHovered &&
            !isArchived && (
              <HuMenuList
                minWidth="240px"
                position="right"
                options={[
                  ...insertIf(!isPinned, {
                    Icon: IconPinned,
                    title: t('pin_group_web'),
                    onClick: togglePin,
                  }),
                  ...insertIf(!!isPinned, {
                    Icon: IconPinnedOff,
                    title: t('unpin_group_web'),
                    onClick: togglePin,
                  }),
                ]}
              />
            )
          }
          sx={{
            width: '100%',
            my: 0.5,
          }}
          slotProps={{
            container: {
              sx: {
                padding: 1,
                borderRadius: theme.shape.borderRadiusL,
                '&:hover': {
                  backgroundColor: theme.palette.new.background.elements.grey,
                },
                '&.Mui-selected': {
                  backgroundColor: theme.palette.new.background.elements.grey,
                },
              },
            },
            avatar: {
              src: icon.type !== 'EMOJI' ? icon.value : undefined,
              text: icon.type === 'EMOJI' ? icon.value : undefined,
              alt: title,
              variant: 'square',
              sx: {
                padding: '10px',
                mr: 0.5,
              },
            },
            title: {
              slotProps: {
                title: {
                  sx: {
                    color: exactMatch
                      ? theme.palette.new.text.neutral.default
                      : undefined,
                  },
                },
              },
            },
          }}
        />
      </Stack>
    </HugoProvider>
  );
};

const ThemedNavGroupItem = (props: NavGroupItemProps) => {
  const HugoProvider = useHuGoTheme();

  return (
    <HugoProvider>
      <NavGroupItem {...props} />
    </HugoProvider>
  );
};

export default ThemedNavGroupItem;
