import { useCallback, useEffect, useState } from 'react';
import { useQuery } from 'react-query';

import { useServerPagination } from '@material-hu/hooks/useServerPagination';

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

import { logEvent } from 'src/config/logging';
import { EVENTS_SOCKETS } from 'src/constants/sockets';
import { useAuth } from 'src/contexts/JWTContext';
import { useSocket } from 'src/contexts/SocketContext';
import useHuGoTheme from 'src/hooks/useHuGoTheme';
import useRequiredParams from 'src/hooks/useRequiredParams';
import {
  getGroupPendingApprovalPosts,
  reviewGroupPosts,
} from 'src/services/groups';
import { OrderBy } from 'src/types/feed';
import { ApprovalStatus, type GroupPendingPost } from 'src/types/groups';
import { PostRequestActionType } from 'src/types/posts';
import { useLokaliseTranslation as useTranslation } from 'src/utils/i18n';
import { type PaginationParams } from 'src/utils/pagination';

import PendingPostsApproval from '../../../../../components/pendingApprovals/PendingPostsApproval';
import {
  groupsKeys,
  invalidateGroupPendingApprovalPostList,
  invalidateGroupPost,
} from '../../queries';
import { invalidateFeedPostDetail } from 'src/pages/dashboard/feed/queries';

const GroupPendingPostsApproval = () => {
  const { enqueueSnackbar } = useSnackbar();
  const socket = useSocket();

  const { id: groupId } = useRequiredParams(['id']);
  const { t } = useTranslation(['group']);
  const { user } = useAuth();
  const HuGoThemeProvider = useHuGoTheme();
  const [selectedActionType, setSelectedActionType] =
    useState<PostRequestActionType>(PostRequestActionType.CREATION);

  const serverPagination = useServerPagination({
    labelRowsPerPage: t('ROWS_PER_PAGE'),
    defaultOrderBy: 'CREATED_AT',
    defaultOrder: OrderBy.DESC,
    defaultLimit: 5,
    limitOptions: [5, 10, 20, 50],
  });

  const paginationAndOrder: PaginationParams = {
    ...serverPagination.pagination,
    page: serverPagination.pagination.page + 1,
    order: serverPagination.order,
    orderBy: serverPagination.orderBy,
  };

  // One query per action type so keepPreviousData only applies within a tab (pagination
  // / sort / page size). A single query with keepPreviousData would briefly show the
  // other tab's rows when switching CREATION ↔ EDITION.
  const pendingPostsQueryOptions = {
    select: (r: Awaited<ReturnType<typeof getGroupPendingApprovalPosts>>) =>
      r.data,
    keepPreviousData: true,
    onError: () => {
      enqueueSnackbar({
        title: t('group:pending_approval_posts_loading_error'),
        variant: 'error',
      });
    },
  } as const;

  const creationPendingPostsQuery = useQuery(
    groupsKeys.pendingApproval.postList(groupId, {
      ...paginationAndOrder,
      actionType: PostRequestActionType.CREATION,
    }),
    () =>
      getGroupPendingApprovalPosts(
        groupId,
        paginationAndOrder,
        ApprovalStatus.PENDING,
        PostRequestActionType.CREATION,
      ),
    {
      ...pendingPostsQueryOptions,
      enabled:
        !!groupId && selectedActionType === PostRequestActionType.CREATION,
    },
  );

  const editionPendingPostsQuery = useQuery(
    groupsKeys.pendingApproval.postList(groupId, {
      ...paginationAndOrder,
      actionType: PostRequestActionType.EDITION,
    }),
    () =>
      getGroupPendingApprovalPosts(
        groupId,
        paginationAndOrder,
        ApprovalStatus.PENDING,
        PostRequestActionType.EDITION,
      ),
    {
      ...pendingPostsQueryOptions,
      enabled:
        !!groupId && selectedActionType === PostRequestActionType.EDITION,
    },
  );

  const pendingPostsQuery =
    selectedActionType === PostRequestActionType.CREATION
      ? creationPendingPostsQuery
      : editionPendingPostsQuery;

  const invalidatePendingPosts = useCallback(() => {
    invalidateGroupPendingApprovalPostList(groupId);
  }, [groupId]);

  useEffect(() => {
    socket.listenEvent(
      EVENTS_SOCKETS.GROUP_POST_REQUEST,
      invalidatePendingPosts,
    );
    socket.listenEvent(
      EVENTS_SOCKETS.GROUP_POST_REQUEST_APPROVED,
      invalidatePendingPosts,
    );
    socket.listenEvent(
      EVENTS_SOCKETS.GROUP_POST_REQUEST_REJECTED,
      invalidatePendingPosts,
    );
    return () => {
      socket.closeEvent(
        EVENTS_SOCKETS.GROUP_POST_REQUEST,
        invalidatePendingPosts,
      );
      socket.closeEvent(
        EVENTS_SOCKETS.GROUP_POST_REQUEST_APPROVED,
        invalidatePendingPosts,
      );
      socket.closeEvent(
        EVENTS_SOCKETS.GROUP_POST_REQUEST_REJECTED,
        invalidatePendingPosts,
      );
    };
  }, [socket, invalidatePendingPosts]);

  return (
    <HuGoThemeProvider>
      <PendingPostsApproval
        pendingPostsQuery={pendingPostsQuery}
        reviewPostsService={({ approvalStatus, postIds }) =>
          reviewGroupPosts(groupId, approvalStatus, postIds)
        }
        selectedActionType={selectedActionType}
        onActionTypeChange={setSelectedActionType}
        onReviewSuccess={(variables, pendingPosts) => {
          const list = pendingPosts as GroupPendingPost[];
          const acceptedUserIds = variables.postIds.map(
            (postId: number) =>
              list.find(pendingPost => pendingPost.id === postId)?.groupPost
                .user.id,
          );
          logEvent(`GROUPS_POST_${variables.approvalStatus}`, {
            resolutionUserId: user?.id,
            acceptedUserIds,
            postIds: variables.postIds,
            groupId,
          });
          invalidatePendingPosts();
          if (
            variables.approvalStatus === ApprovalStatus.APPROVED &&
            selectedActionType === PostRequestActionType.EDITION
          ) {
            variables.postIds.forEach(requestId => {
              const pp = list.find(p => p.id === requestId);
              if (!pp || pp.actionType !== PostRequestActionType.EDITION) {
                return;
              }
              invalidateGroupPost(groupId, pp.groupPost.id);
              // Keep feed detail cache in sync for group posts visible in feed
              invalidateFeedPostDetail(pp.groupPost.id);
            });
          }
        }}
        serverPagination={serverPagination}
        sx={{ py: 0 }}
      />
    </HuGoThemeProvider>
  );
};

export default GroupPendingPostsApproval;
