import { type FC, Fragment, memo, useState } from 'react';
import {
  type FetchNextPageOptions,
  type InfiniteData,
  type InfiniteQueryObserverResult,
  useInfiniteQuery,
  useQuery,
} from 'react-query';

import { type AxiosResponse } from 'axios';
import { useDrawerV2 } from '@material-hu/hooks/useDrawerV2';
import { IconCheck, IconProgressCheck } from '@material-hu/icons/tabler';
import Stack from '@material-hu/mui/Stack';

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

import useGeneralError from 'src/hooks/useGeneralError';
import usePermissions from 'src/hooks/usePermissions';
import { feedKeys } from 'src/pages/dashboard/feed/queries';
import { useGroupMember } from 'src/pages/dashboard/groups/GroupMemberContext';
import { groupsKeys } from 'src/pages/dashboard/groups/queries';
import { getGroupPendingApprovalPosts } from 'src/services/groups';
import { getFeedPendingApprovalPosts } from 'src/services/posts';
import { type FeedPendingApprovalPostList } from 'src/types/feed';
import {
  ApprovalStatus,
  type GroupPendingApprovalPostList,
} from 'src/types/groups';
import { PostRequestActionType } from 'src/types/posts';
import { useLokaliseTranslation as useTranslation } from 'src/utils/i18n';
import { UserPermissions } from 'src/utils/permissions';

import InfiniteList from 'src/components/list/InfiniteList';
import EmptyState from 'src/pages/dashboard/communication/DraftsForReview/components/EmptyState';

import AlertAccordion from './AlertAccordion';
import { PendingApprovalPostListCard } from './PendingApprovalPostListCard';
import { PENDING_REQUEST_TABS } from './pendingRequestTabs';

const getPendingApprovalPostsDrawerConfig = ({
  t,
  pendingApprovalPosts,
  isLoading,
  fetchNextPage,
  hasNextPage,
  isFetchingNextPage,
  closeDrawer,
  selectedActionType,
  onActionTypeChange,
}: {
  t: (key: string) => string;
  pendingApprovalPosts:
    | InfiniteData<
        AxiosResponse<
          FeedPendingApprovalPostList | GroupPendingApprovalPostList,
          unknown
        >
      >
    | undefined;
  isLoading: boolean;
  hasNextPage: boolean | undefined;
  isFetchingNextPage: boolean;
  closeDrawer: () => void;
  selectedActionType: PostRequestActionType;
  onActionTypeChange: (actionType: PostRequestActionType) => void;
} & {
  fetchNextPage: (
    options?: FetchNextPageOptions,
  ) => Promise<InfiniteQueryObserverResult<unknown, unknown>>;
}) => {
  const isEmpty =
    !pendingApprovalPosts ||
    pendingApprovalPosts.pages[0].data?.items?.length === 0;
  const showEditedPostsEmptyState =
    !isLoading &&
    isEmpty &&
    selectedActionType === PostRequestActionType.EDITION;

  return {
    title: t('pending_approval_posts'),
    children: (
      <Stack sx={{ p: 2, mb: 8, gap: 2, overflowY: 'auto' }}>
        <Tabs
          value={selectedActionType}
          tabs={PENDING_REQUEST_TABS.map(tab => ({
            label: t(tab.labelKey),
            value: tab.value,
          }))}
          onTabChange={value =>
            onActionTypeChange(value as PostRequestActionType)
          }
        />
        <InfiniteList
          isSuccess={!!pendingApprovalPosts}
          isEmpty={isEmpty}
          noResultsLabel={
            selectedActionType === PostRequestActionType.EDITION
              ? t('no_edited_posts')
              : undefined
          }
          showNoResultsMessage={!showEditedPostsEmptyState}
          isLoading={isLoading}
          fetchNextPage={fetchNextPage}
          hasNextPage={hasNextPage}
          isFetchingNextPage={isFetchingNextPage}
          sx={{ overflowY: 'unset' }}
        >
          {pendingApprovalPosts?.pages?.map((page, index) => (
            <Fragment key={index}>
              {page.data?.items?.map(pendingPost => (
                <PendingApprovalPostListCard
                  key={pendingPost.id}
                  pendingPost={pendingPost}
                  closeScheduledPostList={closeDrawer}
                />
              ))}
            </Fragment>
          ))}
        </InfiniteList>
        {showEditedPostsEmptyState && (
          <EmptyState
            titleProps={{
              title: t('no_edited_posts'),
              description: '',
            }}
            avatarProps={{
              Icon: IconCheck,
              color: 'success',
            }}
            sx={{ backgroundColor: 'transparent' }}
          />
        )}
      </Stack>
    ),
    onClose: closeDrawer,
  };
};

type Props = {
  groupId?: string;
};
const PendingApprovalPostList: FC<Props> = ({ groupId }) => {
  const [selectedActionType, setSelectedActionType] =
    useState<PostRequestActionType>(PostRequestActionType.CREATION);
  const { hasAll: canApproveFeedPosts } = usePermissions([
    UserPermissions.CAN_APPROVE_FEED_POSTS,
  ]);
  const groupMember = useGroupMember();

  const { userIsMember, isGroupAdmin, isGroupArchived } = groupId
    ? groupMember
    : {
        userIsMember: true,
        isGroupAdmin: canApproveFeedPosts,
        isGroupArchived: false,
      };
  const { t } = useTranslation('post');
  const showGeneralError = useGeneralError();

  const { pendingApprovalPostsListQuery, pendingApprovalPostsCountQuery } =
    groupId
      ? {
          pendingApprovalPostsListQuery: {
            key: groupsKeys.pendingApproval.postList(groupId, {
              limit: 10,
              actionType: selectedActionType,
            }),
            queryFn: () =>
              getGroupPendingApprovalPosts(
                groupId,
                { limit: 10, page: 1 },
                ApprovalStatus.PENDING,
                selectedActionType,
              ),
          },
          pendingApprovalPostsCountQuery: {
            key: groupsKeys.pendingApproval.postList(groupId, {
              limit: 1,
            }),
            queryFn: () =>
              getGroupPendingApprovalPosts(
                groupId,
                { limit: 1, page: 1 },
                ApprovalStatus.PENDING,
                undefined,
              ),
          },
        }
      : {
          pendingApprovalPostsListQuery: {
            key: feedKeys.pendingApproval.postList({
              limit: 10,
              actionType: selectedActionType,
            }),
            queryFn: () =>
              getFeedPendingApprovalPosts(
                { limit: 10, page: 1 },
                ApprovalStatus.PENDING,
                selectedActionType,
              ),
          },
          pendingApprovalPostsCountQuery: {
            key: feedKeys.pendingApproval.postList({
              limit: 1,
            }),
            queryFn: () =>
              getFeedPendingApprovalPosts(
                { limit: 1, page: 1 },
                ApprovalStatus.PENDING,
                undefined,
              ),
          },
        };

  const {
    data: pendingApprovalPosts,
    isLoading,
    fetchNextPage,
    hasNextPage,
    isFetchingNextPage,
  } = useInfiniteQuery<
    AxiosResponse<FeedPendingApprovalPostList | GroupPendingApprovalPostList>
  >(pendingApprovalPostsListQuery.key, pendingApprovalPostsListQuery.queryFn, {
    getNextPageParam: (_, pages) => {
      const { page, totalPages } = pages[pages.length - 1]?.data || {};
      return page < totalPages ? pages.length + 1 : undefined;
    },
    onError: err => {
      showGeneralError(err, t('post:error_loading_pending_approval_posts'));
    },
    enabled: userIsMember && !isGroupAdmin,
  });

  const {
    data: count = 0,
    isLoading: countIsLoading,
    isError: countIsError,
  } = useQuery<
    AxiosResponse<FeedPendingApprovalPostList | GroupPendingApprovalPostList>,
    unknown,
    number
  >(
    pendingApprovalPostsCountQuery.key,
    pendingApprovalPostsCountQuery.queryFn as () => Promise<
      AxiosResponse<FeedPendingApprovalPostList | GroupPendingApprovalPostList>
    >,
    {
      select: response => response.data.count,
      enabled: userIsMember && !isGroupAdmin,
    },
  );

  const { showDrawer, drawer } = useDrawerV2(({ closeDrawer }) =>
    getPendingApprovalPostsDrawerConfig({
      t,
      pendingApprovalPosts,
      isLoading,
      fetchNextPage,
      hasNextPage,
      isFetchingNextPage,
      selectedActionType,
      onActionTypeChange: setSelectedActionType,
      closeDrawer,
    }),
  );

  const openScheduledPostList = () => showDrawer({});

  if (isGroupAdmin || isGroupArchived) return null;

  return (
    <>
      {(countIsLoading || countIsError || !!count) && (
        <AlertAccordion
          Icon={IconProgressCheck}
          title={
            countIsLoading || countIsError
              ? t('pending_approval_posts')
              : t('approve_amount', { count })
          }
          description={t('approve_description')}
          buttonTitle={t('see_post')}
          onClick={openScheduledPostList}
        />
      )}
      {drawer}
    </>
  );
};

export default memo(PendingApprovalPostList);
