import { FC, useMemo } from 'react';
import { useInfiniteQuery, useQuery } from 'react-query';
import { useLocation, useNavigate } from 'react-router-dom';

import qs from 'qs';
import Box from '@material-hu/mui/Box';

import useSnackbar from '@material-hu/components/design-system/Snackbar';

import { logEvent } from 'src/config/logging';
import { useAuth } from 'src/contexts/JWTContext';
import useGeneralError from 'src/hooks/useGeneralError';
import usePostsViewTracking from 'src/pages/dashboard/feed/hooks/usePostsViewTracking';
import MarketplacePostAddDrawer from 'src/pages/dashboard/marketplace/components/MarketplacePostAddDrawer';
import MarketplacePostCard from 'src/pages/dashboard/marketplace/components/MarketplacePostCard';
import {
  marketplaceKeys,
  setMarketplaceDetailData,
  setMyMarketplaceListData,
  updateMarketplacePostReaction,
} from 'src/pages/dashboard/marketplace/queries';
import {
  getById,
  getMyList,
  updateMarketplacePost,
} from 'src/services/marketplace';
import { EventName } from 'src/types/amplitude';
import { MarketplacePost } from 'src/types/marketplace';
import { splitByTypes } from 'src/utils/attachments';
import { getFormFileFromAttachment } from 'src/utils/files';
import { useLokaliseTranslation as useTranslation } from 'src/utils/i18n';
import { addReaction, removeReaction } from 'src/utils/reactions';

import InfiniteList from 'src/components/list/InfiniteList';

const MyMarketplacePostList: FC = () => {
  const { t } = useTranslation(['marketplace', 'general']);
  const { enqueueSnackbar } = useSnackbar();
  const location = useLocation();
  const navigate = useNavigate();
  const { user } = useAuth();
  const showGeneralError = useGeneralError();

  const { id } = qs.parse(location.search, { ignoreQueryPrefix: true }) as {
    id: string;
  };
  const isEdit = location.hash === '#edit';

  const { data, isLoading, fetchNextPage, hasNextPage, isFetchingNextPage } =
    useInfiniteQuery(
      marketplaceKeys.mine(),
      ({ pageParam = '' }) => getMyList(pageParam),
      {
        getNextPageParam: lastPage =>
          lastPage.data?.length > 0
            ? lastPage.data[lastPage.data.length - 1].createdAt
            : undefined,
        onError: () => {
          enqueueSnackbar({
            title: t('marketplace:error_loading_posts'),
            variant: 'error',
          });
        },
      },
    );

  const { data: detailData } = useQuery(
    marketplaceKeys.detail(id),
    () => getById(Number(id)),
    {
      onError: () => {
        navigate('');
        enqueueSnackbar({
          title: t('marketplace:error_loading_post_detail'),
          variant: 'error',
        });
      },
      enabled: isEdit && !!id,
    },
  );

  const post = detailData?.data || ({} as MarketplacePost);

  const handleCancel = () => {
    navigate('');
  };

  const handleSuccess = (successPost: MarketplacePost) => {
    logEvent(EventName.POST_MARKETPLACE_UPDATE, { postId: post?.id });

    enqueueSnackbar({
      title: t('marketplace:post_edited'),
      variant: 'success',
    });

    setMyMarketplaceListData(successPost.id, successPost);
    setMarketplaceDetailData(successPost.id, successPost);
    navigate('');
  };

  const handleError = (error: Error) => {
    showGeneralError(error, t('marketplace:error_edit_post'));
  };

  const handleAddReaction = (
    postId: number,
    emoji: string,
    unified: string,
  ) => {
    updateMarketplacePostReaction(postId, emoji, reactions =>
      addReaction(reactions, emoji, unified),
    );
  };

  const handleRemoveReaction = (postId: number, emoji: string) => {
    updateMarketplacePostReaction(postId, emoji, reactions =>
      removeReaction(reactions, emoji),
    );
  };

  const {
    images: imagesAttachments,
    videos: videosAttachments,
    files: filesAttachments,
  } = splitByTypes(post.attachments);

  const images = imagesAttachments.map(getFormFileFromAttachment);
  const videos = videosAttachments.map(getFormFileFromAttachment);
  const files = filesAttachments.map(getFormFileFromAttachment);

  const allPosts = useMemo(
    () => data?.pages?.flatMap(page => page.data) ?? [],
    [data],
  );

  const postsForViewTracking = useMemo(
    () =>
      allPosts
        .filter(_post => _post.user.id !== user?.id)
        .map(_post => ({ id: _post.id })),
    [allPosts],
  );

  usePostsViewTracking({
    posts: postsForViewTracking,
    context: 'marketplace',
  });

  return (
    <>
      <MarketplacePostAddDrawer
        request={requestData => updateMarketplacePost(Number(id), requestData)}
        open={isEdit && !!detailData?.data}
        isEdit
        onCancel={handleCancel}
        onSuccess={handleSuccess}
        onError={handleError}
        defaultBody={post.body}
        defaultBodyAttributes={post.bodyAttributes}
        defaultPrice={{ amount: post.price, currencyCode: post.currencyCode }}
        defaultImages={images}
        defaultVideos={videos}
        defaultFiles={files}
      />
      <InfiniteList
        isSuccess={!!data}
        isLoading={isLoading}
        isEmpty={!data?.pages[0]?.data?.length}
        noResultsLabel={t('marketplace:no_results_marketplace_post_list')}
        fetchNextPage={fetchNextPage}
        hasNextPage={hasNextPage}
        isFetchingNextPage={isFetchingNextPage}
      >
        {allPosts.map(postItem => (
          <Box
            key={postItem.id}
            data-post-id={postItem.id}
            sx={{ mt: 3 }}
          >
            <MarketplacePostCard
              {...postItem}
              onAddReaction={handleAddReaction}
              onRemoveReaction={handleRemoveReaction}
            />
          </Box>
        ))}
      </InfiniteList>
    </>
  );
};

export default MyMarketplacePostList;
