import { type FC, memo, useEffect, useMemo, useState } from 'react';
import { useInfiniteQuery } from 'react-query';
import { useNavigate } from 'react-router-dom';

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

import { useAuth } from 'src/contexts/JWTContext';
import { useScrollPosition } from 'src/contexts/ScrollPosition';
import useFeed from 'src/hooks/queryHooks/feed';
import useCommunityFeature from 'src/hooks/useCommunityFeature';
import useGeneralError from 'src/hooks/useGeneralError';
import useHuGoTheme from 'src/hooks/useHuGoTheme';
import { useScrollRestoration } from 'src/hooks/useScrollRestoration';
import usePostsViewTracking from 'src/pages/dashboard/feed/hooks/usePostsViewTracking';
import {
  addFeedAndPinListDataReaction,
  feedKeys,
  removeFeedAndPinListDataReaction,
} from 'src/pages/dashboard/feed/queries';
import { feedRoutes } from 'src/pages/dashboard/feed/routes';
import { getList } from 'src/services/posts';
import { CommunityFeature } from 'src/types/communityFeatures';
import { getLastPinnedPost, isPostPinned } from 'src/utils/feed';
import { useLokaliseTranslation as useTranslation } from 'src/utils/i18n';
import { withShareMetadata } from 'src/utils/sharedPost';

import InfiniteList from 'src/components/list/InfiniteList';
import PinnedPostPreview from 'src/components/post/PinnedPostPreview';
import PostCard from 'src/components/post/PostCard';

import FeedPostSkeleton from '../../events/components/skeleton/FeedPostSkeleton';

export type PostListProps = {};

export const PostList: FC<PostListProps> = () => {
  const { user, instance, permissions } = useAuth();
  const navigate = useNavigate();

  const showGeneralError = useGeneralError();
  const { t } = useTranslation(['post']);
  const { pinnedPosts: pinnedPostsQuery } = useFeed();
  const { data: pinnedPostsData } = pinnedPostsQuery();
  const HugoThemeProvider = useHuGoTheme();
  const { scrollPosition, setScrollPosition } = useScrollPosition();
  const [isScrollRestorationDisabled, setIsScrollRestorationDisabled] =
    useState(false);

  const canViewGroupPostsInFeed = useCommunityFeature(
    CommunityFeature.VIEW_GROUP_POSTS_IN_FEED,
  );

  const {
    data,
    isLoading,
    fetchNextPage,
    hasNextPage,
    isFetchingNextPage,
    isFetching,
  } = useInfiniteQuery(
    feedKeys.list(),
    ({ pageParam = '' }) => getList(pageParam, canViewGroupPostsInFeed),
    {
      getNextPageParam: lastPage => lastPage.data.cursor,
      onError: err => {
        showGeneralError(err, t('post:error_loading_posts'));
      },
      enabled: permissions.length > 0,
    },
  );

  const posts = data?.pages?.flatMap(page => page.data?.items || []) || [];

  const pinnedPosts = useMemo(
    () =>
      pinnedPostsData?.pages?.flatMap(page => page?.data?.items || []) || [],
    [pinnedPostsData],
  );
  const pinnedPostsCount = pinnedPosts.length;

  const lastPinnedPost = useMemo(
    () => getLastPinnedPost(pinnedPosts),
    [pinnedPosts],
  );

  // Filter out ALL pinned posts from regular feed
  const unpinnedPosts = useMemo(() => {
    const pinnedPostIds = new Set(pinnedPosts.map(p => p.id));

    return posts.filter(post => !pinnedPostIds.has(post.id));
  }, [posts, pinnedPosts]);

  usePostsViewTracking({
    posts: [...(lastPinnedPost ? [lastPinnedPost] : []), ...unpinnedPosts]
      .filter(post => !post.viewed)
      .map(post => withShareMetadata.toViewTrackingPost(post)),
    userId: user?.id,
    instanceId: instance?.id,
    context: 'feed',
  });

  useEffect(() => {
    let timeoutId: NodeJS.Timeout;

    const handleScroll = () => {
      // Disable scroll restoration when user scrolls
      setIsScrollRestorationDisabled(true);

      clearTimeout(timeoutId);
      timeoutId = setTimeout(() => {
        const element = document.getElementById('dashboard-layout-content');
        if (element) {
          setScrollPosition(element.scrollTop);
        }
      }, 300); // Throttle to 300ms
    };

    const element = document.getElementById('dashboard-layout-content');
    element?.addEventListener('scroll', handleScroll, { passive: true });

    return () => {
      element?.removeEventListener('scroll', handleScroll);
      clearTimeout(timeoutId);
    };
  }, [setScrollPosition]);

  useScrollRestoration({
    scrollPosition,
    containerId: 'dashboard-layout-content',
    maxLayoutShifts: 5,
    layoutShiftDelay: 100,
    disabled: isScrollRestorationDisabled,
  });

  const handleViewAllPinnedPosts = () => {
    navigate(feedRoutes.pinnedPosts());
  };

  return (
    <InfiniteList
      isSuccess={!!data}
      isLoading={isLoading || isFetching}
      loadingSkeleton={isLoading}
      fetchNextPage={fetchNextPage}
      hasNextPage={hasNextPage}
      isFetchingNextPage={isFetchingNextPage}
      renderSkeleton={
        <HugoThemeProvider>
          <Stack
            sx={{
              gap: 2,
              pt: 2,
              '.MuiPaper-root': {
                borderColor: theme => theme.palette.new.border.neutral.default,
              },
            }}
          >
            {Array.from({ length: 3 }, (_, i) => (
              <FeedPostSkeleton key={`skeleton-${i}`} />
            ))}
          </Stack>
        </HugoThemeProvider>
      }
    >
      {lastPinnedPost && (
        <>
          <Box sx={{ mt: 2 }} />
          <PinnedPostPreview
            postId={lastPinnedPost.id}
            pinnedPostsCount={pinnedPostsCount}
            onViewAllPinnedPosts={handleViewAllPinnedPosts}
          >
            <PostCard
              post={lastPinnedPost}
              isPinned
              hidePinIcon
              hideTranslation
              onAddReaction={addFeedAndPinListDataReaction}
              onRemoveReaction={removeFeedAndPinListDataReaction}
            />
          </PinnedPostPreview>
        </>
      )}
      {unpinnedPosts.map(post => (
        <Box
          key={post.id}
          sx={{ mt: 2 }}
          data-post-id={post.id}
        >
          <PostCard
            isPinned={isPostPinned(pinnedPosts, post)}
            onAddReaction={addFeedAndPinListDataReaction}
            onRemoveReaction={removeFeedAndPinListDataReaction}
            post={post}
          />
        </Box>
      ))}
    </InfiniteList>
  );
};

export default memo(PostList);
