import { type InfiniteData } from 'react-query';

import { type AxiosResponse } from 'axios';

import { logEvent } from 'src/config/logging';
import { queryClient } from 'src/config/react-query';
import {
  acknowledgementsKeys,
  dropChildCommentDataChildCommentList as dropChildCommentDataChildCommentListAck,
  dropChildCommentDataCommentList as dropChildCommentDataCommentListAck,
  dropChildLastCommentDataAcknowledgementList,
  dropCommentDataChildCommentList as dropCommentDataChildCommentListAck,
  dropCommentDataCommentList as dropCommentDataCommentListAck,
  dropLastCommentDataAcknowledgementList,
  increaseAcknowledgementCommentAmount,
  pushChildCommentDataChildCommentList as pushChildCommentDataChildCommentListAck,
  pushChildCommentDataCommentList as pushChildCommentDataCommentListAck,
  pushChildLastCommentDataAcknowledgementList,
  pushLastCommentData,
  setChildCommentDataChildCommentList as setChildCommentDataChildCommentListAck,
  setChildCommentDataCommentList as setChildCommentDataCommentListAck,
  setChildLastCommentDataAcknowledgementList,
  unshiftCommentDataCommentList as unshiftCommentDataCommentListAck,
  updateCommentListData as updateCommentListDataAck,
  updateLastCommentData,
  updateReactionChildComment,
  updateReactionComment,
} from 'src/pages/dashboard/acknowledgements/queries';
import {
  getChildCommentsPaginated as getAcknowledgementChildCommentsPaginated,
  getAcknowledgementsCommentsPaginated,
  postComment as postAcknowledgementComment,
} from 'src/pages/dashboard/acknowledgements/services';
import {
  dropEventPostChildComment,
  dropEventPostComment,
  eventsKeys,
  invalidateEventPostChildComment,
  invalidateEventPostComment,
  unshiftEventPostChildComment,
  unshiftEventPostComment,
  updateEventPostChildComment,
  updateEventPostChildCommentReaction,
  updateEventPostComment,
  updateEventPostCommentReaction,
} from 'src/pages/dashboard/events/queries';
import {
  dropChildComment,
  dropComment,
  feedKeys,
  unshiftChildComment,
  unshiftComment,
  updateChildComment,
  updateComment,
  updateReactionChildCommentData,
  updateReactionCommentData,
} from 'src/pages/dashboard/feed/queries';
import {
  dropGroupChildComment,
  dropGroupComment,
  groupsKeys,
  unshiftGroupChildComment,
  unshiftGroupComment,
  updateGroupChildComment,
  updateGroupComment,
  updateGroupReactionChildCommentData,
  updateGroupReactionCommentData,
} from 'src/pages/dashboard/groups/queries';
import {
  decreaseMarketplacePostCommentAmount,
  dropChildCommentDataChildCommentList as dropChildCommentDataChildCommentListMarketplace,
  dropChildCommentDataCommentList as dropChildCommentDataCommentListMarketplace,
  dropChildLastCommentDataMarketplaceList,
  dropChildLastCommentDataMarketplacePostDetail,
  dropChildLastCommentDataMyMarketplaceList,
  dropCommentDataChildCommentList as dropCommentDataChildCommentListMarketplace,
  dropCommentDataCommentList as dropCommentDataCommentListMarketplace,
  dropCommentMarketplaceDetail,
  dropCommentMarketplaceList,
  dropCommentMyMarketplaceList,
  increaseMarketplacePostCommentAmount,
  marketplaceKeys,
  unshiftChildLastCommentDataMarketplaceList,
  unshiftChildLastCommentDataMarketplacePostDetail,
  unshiftChildLastCommentDataMyMarketplaceList,
  unshiftLastCommentDataMarketplaceList,
  unshiftLastCommentDataMarketplacePostDetail,
  unshiftLastCommentDataMyMarketplaceList,
  updateChildCommentData as updateMarketplaceChildCommentData,
  updateCommentData as updateMarketplaceCommentData,
  updateReactionChildCommentData as updateMarketplaceReactionChildCommentData,
  updateReactionCommentData as updateMarketplaceReactionCommentData,
} from 'src/pages/dashboard/marketplace/queries';
import {
  dropChildCommentDataChildCommentList,
  dropChildCommentDataCommentList,
  dropCommentDataCommentList as dropCommentDataCommentListNews,
  increaseCommentAmountArticleDetail,
  newsKeys,
  setChildCommentDataChildCommentList,
  setChildCommentDataCommentList,
  updateCommentListData,
  updateReactionChildCommentDataChildCommentList,
  updateReactionChildCommentDataCommentList,
  updateReactionCommentDataCommentList,
} from 'src/pages/dashboard/news/queries';
import {
  getEventChildCommentsPaginated,
  getEventPostCommentsPaginated,
  postEventComment,
} from 'src/services/events';
import {
  getGroupPostChildCommentsPaginated,
  getGroupPostCommentsPaginated,
  postGroupComment,
} from 'src/services/groups';
import {
  getChildCommentsPaginated as getMarketplaceChildCommentsPaginated,
  getMarketplacePostCommentsPaginated,
  postComment as postMarketplaceComment,
} from 'src/services/marketplace';
import {
  getChildCommentsPaginated as getArticleChildCommentsPaginated,
  getArticleComments,
  postComment as postArticleComment,
} from 'src/services/news';
import {
  getChildCommentsPaginated,
  getPostCommentsPaginated,
  postComment,
} from 'src/services/posts';
import { EventName } from 'src/types/amplitude';
import {
  type Comment as CommentType,
  type PostCommentPayload,
} from 'src/types/comments';
import { type GroupCommentList } from 'src/types/groups';
import { type Updater } from 'src/types/queries';
import { type Reaction } from 'src/types/reaction';
import { type CursorPagination } from 'src/types/services';
import {
  DEFAULT_LIMIT,
  getListLength,
  getNextCursor,
  getNextPage,
} from 'src/utils/pagination';
import { UserPermissions } from 'src/utils/permissions';

import { type CommentsResponse } from './types';

export type GetChildCommentsQueryConfigReturn = {
  queryKey: (string | number)[];
  queryFn: ({
    pageParam,
  }: {
    pageParam?: string | number;
  }) => Promise<AxiosResponse<CommentsResponse>>;
  getNextPageParam: (
    lastPage: AxiosResponse<CommentsResponse>,
    pages: AxiosResponse<CommentsResponse>[],
  ) => string | number | undefined;
  select?: (
    data: InfiniteData<AxiosResponse<CommentsResponse>>,
  ) => InfiniteData<AxiosResponse<CommentsResponse>>;
};

// Base query function signatures - using proper union types
type QueryFnBase = (
  postId: number,
  pageParam: string | number,
  groupId?: string,
) => Promise<AxiosResponse<CommentsResponse>>;

type NextPageParamFn = (
  lastPage: AxiosResponse<CommentsResponse>,
  pages: AxiosResponse<CommentsResponse>[],
) => string | number | undefined | null;

export type CommentConfig = {
  // Query configuration
  getQueryKey: (postId: number) => (string | number)[];
  queryFn: QueryFnBase;
  getNextPageParam: NextPageParamFn;
  select?: (data: any) => any;

  // Comment operations
  postComment: (
    postId: number,
    body: PostCommentPayload,
  ) => Promise<AxiosResponse<CommentType>>;
  onPostSuccess?: (postId: number, comment: CommentType) => void;
  onReplySuccess?: (
    postId: number,
    parentId: number,
    comment: CommentType,
  ) => void;

  // CRUD operations
  onDeleteSuccess?: (postId: number, commentId: number) => void;
  onDeleteChildSuccess?: (
    postId: number,
    parentId: number,
    commentId: number,
  ) => void;
  onUpdateSuccess?: (postId: number, comment: CommentType) => void;
  onUpdateChildSuccess?: (
    postId: number,
    parentId: number,
    comment: CommentType,
  ) => void;

  // Reaction operations
  onUpdateReactionSuccess?: (
    postId: number,
    commentId: number,
    updater: Updater<Reaction[]>,
  ) => void;
  onUpdateReactionChildSuccess?: (
    postId: number,
    parentId: number,
    commentId: number,
    updater: Updater<Reaction[]>,
  ) => void;

  // Child comments query configuration
  getChildCommentsQueryConfig: (
    comment: CommentType,
    postId: number,
  ) => GetChildCommentsQueryConfigReturn;

  // Permissions
  permissions: {
    react: UserPermissions[];
    manage: UserPermissions[];
  };

  // Logging
  logEvents?: {
    postComment?: (params: any) => void;
    postMention?: (params: any) => void;
  };
};

const COMMENTS_PER_PAGE = 7;

// Helper function to transform group comments to feed format
const postCommentsGroupToFeedTransformer = (
  response: GroupCommentList,
): CommentType[] => response.items;

// Helper to build feed config with proper closures for groupId
const buildFeedConfig = (groupId?: string): CommentConfig => ({
  getQueryKey: postId =>
    groupId
      ? groupsKeys.comment.detail(postId, groupId)
      : feedKeys.comment.detail(postId),
  queryFn: (postId, pageParam) =>
    groupId
      ? getGroupPostCommentsPaginated(
          postId,
          pageParam,
          groupId,
          COMMENTS_PER_PAGE,
          'CREATED_AT',
          'DESC',
        )
      : getPostCommentsPaginated(
          postId,
          pageParam,
          COMMENTS_PER_PAGE,
          'CREATED_AT',
          'DESC',
        ),
  getNextPageParam: (lastPage, pages) =>
    groupId
      ? (getNextCursor(lastPage as AxiosResponse<GroupCommentList>) ??
        undefined)
      : getNextPage(
          getListLength(pages as AxiosResponse<CommentType[]>[]),
          COMMENTS_PER_PAGE,
          pages,
        ),
  select: groupId
    ? (response: any) => ({
        pages: response.pages.map((page: AxiosResponse<GroupCommentList>) => ({
          ...page,
          data: postCommentsGroupToFeedTransformer(page.data),
        })),
        pageParams: response.pageParams,
      })
    : undefined,
  postComment: (postId, body) =>
    groupId
      ? postGroupComment(postId, body, groupId)
      : postComment(postId, body),
  onPostSuccess: (postId, comment) => {
    if (groupId) {
      // Update lastComments and count (for preview)
      unshiftGroupComment(postId, groupId, comment);
      // Invalidate paginated comments to refetch when loaded
      queryClient.invalidateQueries(groupsKeys.comment.detail(postId, groupId));
    } else {
      // Update lastComments and count (for preview)
      unshiftComment(postId, comment);
      // Invalidate paginated comments to refetch when loaded
      queryClient.invalidateQueries(feedKeys.comment.detail(postId));
    }
  },
  onReplySuccess: (postId, parentId, comment) => {
    if (groupId) {
      unshiftGroupChildComment(postId, groupId, parentId, comment);
      queryClient.invalidateQueries(groupsKeys.comment.detail(postId, groupId));
      queryClient.invalidateQueries(
        groupsKeys.childComment.detail(parentId, groupId),
      );
    }

    unshiftChildComment(postId, parentId, comment);
    // Invalidate paginated queries
    queryClient.invalidateQueries(feedKeys.comment.detail(postId));
    queryClient.invalidateQueries(feedKeys.childComment.detail(parentId));
  },
  onDeleteSuccess: (postId, commentId) => {
    groupId
      ? dropGroupComment(postId, groupId, commentId)
      : dropComment(postId, commentId);
  },
  onDeleteChildSuccess: (postId, parentId, commentId) => {
    groupId
      ? dropGroupChildComment(postId, groupId, parentId, commentId)
      : dropChildComment(postId, parentId, commentId);
  },
  onUpdateSuccess: (postId, comment) => {
    groupId
      ? updateGroupComment(postId, groupId, comment)
      : updateComment(postId, comment);
  },
  onUpdateChildSuccess: (postId, parentId, comment) => {
    groupId
      ? updateGroupChildComment(postId, groupId, parentId, comment)
      : updateChildComment(postId, parentId, comment);
  },
  onUpdateReactionSuccess: (postId, commentId, updater) => {
    groupId
      ? updateGroupReactionCommentData(postId, groupId, commentId, updater)
      : updateReactionCommentData(postId, commentId, updater);
  },
  onUpdateReactionChildSuccess: (postId, parentId, commentId, updater) => {
    groupId
      ? updateGroupReactionChildCommentData(
          postId,
          groupId,
          parentId,
          commentId,
          updater,
        )
      : updateReactionChildCommentData(postId, parentId, commentId, updater);
  },
  getChildCommentsQueryConfig: (comment, postId) => {
    if (groupId) {
      return {
        queryKey: groupsKeys.childComment.detail(comment.id, groupId),
        queryFn: ({ pageParam = '' }) =>
          getGroupPostChildCommentsPaginated(
            postId,
            groupId,
            comment.id,
            pageParam as string,
            DEFAULT_LIMIT,
          ),
        getNextPageParam: lastPage =>
          getNextCursor(lastPage as AxiosResponse<GroupCommentList>) ??
          undefined,
        select: response => ({
          pages: response.pages.map(page => ({
            ...page,
            data: postCommentsGroupToFeedTransformer(
              page.data as GroupCommentList,
            ),
          })),
          pageParams: response.pageParams,
        }),
      };
    }
    return {
      queryKey: feedKeys.childComment.detail(comment.id),
      queryFn: ({ pageParam = 1 }) =>
        getChildCommentsPaginated(
          postId,
          comment.id,
          pageParam as number,
          DEFAULT_LIMIT,
        ),
      getNextPageParam: (_, pages) =>
        getNextPage(getListLength(pages), DEFAULT_LIMIT, pages),
    };
  },
  permissions: {
    react: [UserPermissions.CAN_REACT_CONTENT, UserPermissions.CAN_REACT_POSTS],
    manage: [
      UserPermissions.MANAGE_COMMENTS,
      UserPermissions.MANAGE_FEED_COMMENTS,
    ],
  },
  logEvents: {
    postComment: params => logEvent(EventName.POST_COMMENT, params),
    postMention: params => logEvent(EventName.POST_COMMENT_MENTION, params),
  },
});

// Helper to build groups config with proper closures for groupId
const buildGroupsConfig = (groupId: string): CommentConfig => ({
  getQueryKey: postId => groupsKeys.comment.detail(postId, groupId),
  queryFn: (postId, pageParam) =>
    getGroupPostCommentsPaginated(
      postId,
      pageParam,
      groupId,
      COMMENTS_PER_PAGE,
      'CREATED_AT',
      'DESC',
    ),
  getNextPageParam: lastPage =>
    getNextCursor(lastPage as AxiosResponse<GroupCommentList>) ?? undefined,
  select: (response: any) => ({
    pages: response.pages.map((page: AxiosResponse<GroupCommentList>) => ({
      ...page,
      data: postCommentsGroupToFeedTransformer(page.data),
    })),
    pageParams: response.pageParams,
  }),
  postComment: (postId, body) => postGroupComment(postId, body, groupId),
  onPostSuccess: (postId, comment) => {
    // Update lastComments and count (for preview)
    unshiftGroupComment(postId, groupId, comment);
    // Invalidate paginated comments to refetch when loaded
    queryClient.invalidateQueries(groupsKeys.comment.detail(postId, groupId));
  },
  onReplySuccess: (postId, parentId, comment) => {
    unshiftGroupChildComment(postId, groupId, parentId, comment);
    // Invalidate paginated queries
    queryClient.invalidateQueries(groupsKeys.comment.detail(postId, groupId));
    queryClient.invalidateQueries(
      groupsKeys.childComment.detail(parentId, groupId),
    );
  },
  onDeleteSuccess: (postId, commentId) => {
    dropGroupComment(postId, groupId, commentId);
  },
  onDeleteChildSuccess: (postId, parentId, commentId) => {
    dropGroupChildComment(postId, groupId, parentId, commentId);
  },
  onUpdateSuccess: (postId, comment) => {
    updateGroupComment(postId, groupId, comment);
  },
  onUpdateChildSuccess: (postId, parentId, comment) => {
    updateGroupChildComment(postId, groupId, parentId, comment);
  },
  onUpdateReactionSuccess: (postId, commentId, updater) => {
    updateGroupReactionCommentData(postId, groupId, commentId, updater);
  },
  onUpdateReactionChildSuccess: (postId, parentId, commentId, updater) => {
    updateGroupReactionChildCommentData(
      postId,
      groupId,
      parentId,
      commentId,
      updater,
    );
  },
  getChildCommentsQueryConfig: (comment, postId) => ({
    queryKey: groupsKeys.childComment.detail(comment.id, groupId),
    queryFn: ({ pageParam = '' }) =>
      getGroupPostChildCommentsPaginated(
        postId,
        groupId,
        comment.id,
        pageParam as string,
        DEFAULT_LIMIT,
      ),
    getNextPageParam: lastPage =>
      getNextCursor(lastPage as AxiosResponse<GroupCommentList>) ?? undefined,
  }),
  permissions: {
    react: [UserPermissions.CAN_REACT_CONTENT, UserPermissions.CAN_REACT_POSTS],
    manage: [
      UserPermissions.MANAGE_COMMENTS,
      UserPermissions.MANAGE_FEED_COMMENTS,
    ],
  },
  logEvents: {
    postComment: params => logEvent(EventName.GROUPS_POST_COMMENTED, params),
    postMention: params =>
      logEvent(EventName.GROUPS_POST_COMMENT_MENTIONED, params),
  },
});

const commentConfigBuilders: Record<
  string,
  (groupId?: string, eventId?: number) => CommentConfig
> = {
  feed: groupId => buildFeedConfig(groupId),

  groups: groupId => {
    if (!groupId) {
      throw new Error('groupId is required for groups context');
    }
    return buildGroupsConfig(groupId);
  },

  acknowledgements: () => ({
    getQueryKey: postId => acknowledgementsKeys.comment.detail(postId),
    queryFn: (postId, pageParam) =>
      getAcknowledgementsCommentsPaginated(
        postId,
        pageParam,
        COMMENTS_PER_PAGE,
      ),
    getNextPageParam: (_, pages) =>
      getNextPage(getListLength(pages), COMMENTS_PER_PAGE, pages),
    postComment: (postId, body) => postAcknowledgementComment(postId, body),
    onPostSuccess: (postId, comment) => {
      pushLastCommentData(postId, comment);
      increaseAcknowledgementCommentAmount(postId);
      unshiftCommentDataCommentListAck(postId, comment);
    },
    onReplySuccess: (postId, parentId, comment) => {
      pushChildCommentDataCommentListAck(postId, parentId, comment);
      pushChildCommentDataChildCommentListAck(parentId, comment);
      pushChildLastCommentDataAcknowledgementList(postId, parentId, comment);
    },
    onDeleteSuccess: (postId, commentId) => {
      dropLastCommentDataAcknowledgementList(postId, commentId);
      dropCommentDataCommentListAck(postId, commentId);
      dropCommentDataChildCommentListAck(commentId);
    },
    onDeleteChildSuccess: (postId, parentId, commentId) => {
      dropChildCommentDataCommentListAck(postId, parentId, commentId);
      dropChildCommentDataChildCommentListAck(parentId, commentId);
      dropChildLastCommentDataAcknowledgementList(postId, parentId, commentId);
    },
    onUpdateSuccess: (postId, comment) => {
      updateCommentListDataAck(postId, comment.id, comment);
      updateLastCommentData(postId, comment.id, comment);
    },
    onUpdateChildSuccess: (postId, parentId, comment) => {
      setChildCommentDataCommentListAck(postId, parentId, comment.id, comment);
      setChildCommentDataChildCommentListAck(parentId, comment.id, comment);
      setChildLastCommentDataAcknowledgementList(
        postId,
        parentId,
        comment.id,
        comment,
      );
    },
    onUpdateReactionSuccess: (postId, commentId, updater) => {
      updateReactionComment(postId, commentId, updater);
    },
    onUpdateReactionChildSuccess: (postId, parentId, commentId, updater) => {
      updateReactionChildComment(postId, parentId, commentId, updater);
    },
    getChildCommentsQueryConfig: (comment, postId) => ({
      queryKey: acknowledgementsKeys.childComment.detail(comment.id),
      queryFn: ({ pageParam = 1 }) =>
        getAcknowledgementChildCommentsPaginated(
          postId,
          comment.id,
          pageParam as number,
          DEFAULT_LIMIT,
        ),
      getNextPageParam: (_, pages) =>
        getNextPage(getListLength(pages), DEFAULT_LIMIT, pages),
    }),
    permissions: {
      react: [
        UserPermissions.CAN_REACT_CONTENT,
        UserPermissions.CAN_REACT_ACKNOWLEDGEMENTS,
      ],
      manage: [
        UserPermissions.MANAGE_COMMENTS,
        UserPermissions.MANAGE_ACKNOWLEDGEMENTS_COMMENTS,
      ],
    },
  }),

  marketplace: () => ({
    getQueryKey: postId => marketplaceKeys.comment.detail(postId),
    queryFn: (postId, pageParam) =>
      getMarketplacePostCommentsPaginated(
        postId,
        pageParam as number,
        COMMENTS_PER_PAGE,
      ),
    getNextPageParam: (_, pages) =>
      getNextPage(getListLength(pages), COMMENTS_PER_PAGE, pages),
    postComment: (postId, body) => postMarketplaceComment(postId, body),
    onPostSuccess: (postId, comment) => {
      // Update lastComments in all views
      unshiftLastCommentDataMarketplaceList(postId, comment);
      unshiftLastCommentDataMyMarketplaceList(postId, comment);
      unshiftLastCommentDataMarketplacePostDetail(postId, comment);

      // Update comment count
      increaseMarketplacePostCommentAmount(postId);

      // Invalidate paginated comment list so it refetches when loaded
      queryClient.invalidateQueries(marketplaceKeys.comment.detail(postId));
    },
    onReplySuccess: (postId, parentId, comment) => {
      // Update lastComments child comments in all views
      unshiftChildLastCommentDataMarketplaceList(postId, parentId, comment);
      unshiftChildLastCommentDataMyMarketplaceList(postId, parentId, comment);
      unshiftChildLastCommentDataMarketplacePostDetail(
        postId,
        parentId,
        comment,
      );

      // Invalidate paginated queries so they refetch
      queryClient.invalidateQueries(marketplaceKeys.comment.detail(postId));
      queryClient.invalidateQueries(
        marketplaceKeys.childComment.detail(parentId),
      );
    },
    onDeleteSuccess: (postId, commentId) => {
      dropCommentMarketplaceList(postId, commentId);
      dropCommentMyMarketplaceList(postId, commentId);
      dropCommentMarketplaceDetail(postId, commentId);
      dropCommentDataCommentListMarketplace(postId, commentId);
      dropCommentDataChildCommentListMarketplace(commentId);
      decreaseMarketplacePostCommentAmount(postId);
    },
    onDeleteChildSuccess: (postId, parentId, commentId) => {
      dropChildCommentDataCommentListMarketplace(postId, parentId, commentId);
      dropChildCommentDataChildCommentListMarketplace(parentId, commentId);
      dropChildLastCommentDataMarketplacePostDetail(
        postId,
        parentId,
        commentId,
      );
      dropChildLastCommentDataMarketplaceList(postId, parentId, commentId);
      dropChildLastCommentDataMyMarketplaceList(postId, parentId, commentId);
    },
    onUpdateSuccess: (postId, comment) => {
      updateMarketplaceCommentData(postId, comment.id, comment);
    },
    onUpdateChildSuccess: (postId, parentId, comment) => {
      updateMarketplaceChildCommentData(postId, parentId, comment.id, comment);
    },
    onUpdateReactionSuccess: (postId, commentId, updater) => {
      updateMarketplaceReactionCommentData(postId, commentId, updater);
    },
    onUpdateReactionChildSuccess: (postId, parentId, commentId, updater) => {
      updateMarketplaceReactionChildCommentData(
        postId,
        parentId,
        commentId,
        updater,
      );
    },
    getChildCommentsQueryConfig: (comment, postId) => ({
      queryKey: marketplaceKeys.childComment.detail(comment.id),
      queryFn: ({ pageParam = 1 }) =>
        getMarketplaceChildCommentsPaginated(
          postId,
          comment.id,
          pageParam as number,
          DEFAULT_LIMIT,
        ),
      getNextPageParam: (_, pages) =>
        getNextPage(getListLength(pages), DEFAULT_LIMIT, pages),
    }),
    permissions: {
      react: [
        UserPermissions.CAN_REACT_CONTENT,
        UserPermissions.CAN_REACT_MARKETPLACE_POSTS,
      ],
      manage: [
        UserPermissions.MANAGE_COMMENTS,
        UserPermissions.MANAGE_MARKETPLACE_COMMENTS,
      ],
    },
    logEvents: {
      postComment: params =>
        logEvent(EventName.POST_MARKETPLACE_COMMENT, params),
      postMention: params =>
        logEvent(EventName.POST_MARKETPLACE_COMMENT_MENTION, params),
    },
  }),

  articles: () => ({
    getQueryKey: postId => newsKeys.comment.detail(postId),
    queryFn: (postId, pageParam) => {
      return getArticleComments(
        postId,
        COMMENTS_PER_PAGE,
        pageParam ? Number(pageParam) : undefined,
      );
    },
    getNextPageParam: (_, pages) => {
      return pages.length + 1;
    },
    postComment: (postId, body) => postArticleComment(postId, body),
    onPostSuccess: postId => {
      // Increase comment count
      increaseCommentAmountArticleDetail(postId);
      // Invalidate comment list to refetch
      queryClient.invalidateQueries(newsKeys.comment.detail(postId));
    },
    onReplySuccess: (postId, parentId) => {
      // Invalidate queries to refetch with new child comment
      queryClient.invalidateQueries(newsKeys.comment.detail(postId));
      queryClient.invalidateQueries(newsKeys.childComment.detail(parentId));
    },
    onDeleteSuccess: (postId, commentId) => {
      dropCommentDataCommentListNews(postId, commentId);
    },
    onDeleteChildSuccess: (postId, parentId, commentId) => {
      dropChildCommentDataCommentList(postId, parentId, commentId);
      dropChildCommentDataChildCommentList(parentId, commentId);
    },
    onUpdateSuccess: (postId, comment) => {
      updateCommentListData(postId, comment.id, comment);
    },
    onUpdateChildSuccess: (postId, parentId, comment) => {
      setChildCommentDataCommentList(postId, parentId, comment.id, comment);
      setChildCommentDataChildCommentList(parentId, comment.id, comment);
    },
    onUpdateReactionSuccess: (postId, commentId, updater) => {
      updateReactionCommentDataCommentList(postId, commentId, updater);
    },
    onUpdateReactionChildSuccess: (postId, parentId, commentId, updater) => {
      updateReactionChildCommentDataCommentList(
        postId,
        parentId,
        commentId,
        updater,
      );
      updateReactionChildCommentDataChildCommentList(
        parentId,
        commentId,
        updater,
      );
    },
    getChildCommentsQueryConfig: (comment, articleId) => ({
      queryKey: newsKeys.childComment.detail(comment.id),
      queryFn: ({ pageParam = 1 }) =>
        getArticleChildCommentsPaginated(
          articleId,
          comment.id,
          pageParam as number,
          DEFAULT_LIMIT,
        ),
      getNextPageParam: (_, pages) =>
        getNextPage(getListLength(pages), DEFAULT_LIMIT, pages),
    }),
    permissions: {
      react: [
        UserPermissions.CAN_REACT_CONTENT,
        UserPermissions.CAN_REACT_ARTICLES,
      ],
      manage: [
        UserPermissions.MANAGE_COMMENTS,
        UserPermissions.MANAGE_ARTICLES_COMMENTS,
      ],
    },
  }),

  events: (groupId?: string, eventId?: number) => {
    if (!eventId) {
      throw new Error('eventId is required for events context');
    }
    return {
      getQueryKey: postId => eventsKeys.comment.detail(postId, eventId),
      queryFn: (postId, pageParam) =>
        getEventPostCommentsPaginated(
          eventId,
          postId,
          pageParam as string,
          COMMENTS_PER_PAGE,
          'CREATED_AT',
          'DESC',
        ),
      getNextPageParam: lastPage =>
        getNextCursor(
          lastPage as AxiosResponse<CursorPagination<CommentType[]>>,
        ) ?? undefined,
      select: (response: any) => ({
        pages: response.pages.map(
          (page: AxiosResponse<CursorPagination<CommentType[]>>) => ({
            ...page,
            data: page.data.items || page.data,
          }),
        ),
        pageParams: response.pageParams,
      }),
      postComment: (postId, body) => postEventComment(eventId, postId, body),
      onPostSuccess: (postId, comment) => {
        unshiftEventPostComment(postId, eventId, comment);
        invalidateEventPostComment(postId, eventId);
      },
      onReplySuccess: (postId, parentId, comment) => {
        unshiftEventPostChildComment(postId, eventId, parentId, comment);
        invalidateEventPostComment(postId, eventId);
        invalidateEventPostChildComment(parentId, eventId);
      },
      onDeleteSuccess: (postId, commentId) => {
        dropEventPostComment(postId, eventId, commentId);
        invalidateEventPostComment(postId, eventId);
      },
      onDeleteChildSuccess: (postId, parentId, commentId) => {
        dropEventPostChildComment(postId, eventId, parentId, commentId);
        invalidateEventPostComment(postId, eventId);
        invalidateEventPostChildComment(parentId, eventId);
      },
      onUpdateSuccess: (postId, comment) => {
        updateEventPostComment(postId, eventId, comment);
        invalidateEventPostComment(postId, eventId);
      },
      onUpdateChildSuccess: (postId, parentId, comment) => {
        updateEventPostChildComment(postId, eventId, parentId, comment);
        invalidateEventPostComment(postId, eventId);
        invalidateEventPostChildComment(parentId, eventId);
      },
      onUpdateReactionSuccess: (postId, commentId, updater) => {
        updateEventPostCommentReaction(postId, eventId, commentId, updater);
        invalidateEventPostComment(postId, eventId);
      },
      onUpdateReactionChildSuccess: (postId, parentId, commentId, updater) => {
        updateEventPostChildCommentReaction(
          postId,
          eventId,
          parentId,
          commentId,
          updater,
        );
        invalidateEventPostComment(postId, eventId);
        invalidateEventPostChildComment(parentId, eventId);
      },
      getChildCommentsQueryConfig: (comment, postId) => ({
        queryKey: eventsKeys.childComment.detail(comment.id, eventId),
        queryFn: ({ pageParam = '' }) =>
          getEventChildCommentsPaginated(
            eventId,
            postId,
            comment.id,
            pageParam as string,
            DEFAULT_LIMIT,
          ),
        getNextPageParam: lastPage =>
          getNextCursor(
            lastPage as AxiosResponse<CursorPagination<CommentType[]>>,
          ) ?? undefined,
        select: (response: any) => ({
          pages: response.pages.map(
            (page: AxiosResponse<CursorPagination<CommentType[]>>) => ({
              ...page,
              data: page.data.items || page.data,
            }),
          ),
          pageParams: response.pageParams,
        }),
      }),
      permissions: {
        react: [
          UserPermissions.CAN_REACT_CONTENT,
          UserPermissions.CAN_REACT_POSTS,
        ],
        manage: [
          UserPermissions.MANAGE_COMMENTS,
          UserPermissions.MANAGE_FEED_COMMENTS,
        ],
      },
      logEvents: {
        postComment: params => logEvent(EventName.EVENT_POST_COMMENT, params),
        postMention: params =>
          logEvent(EventName.EVENT_POST_COMMENT_MENTION, params),
      },
    };
  },
};

/**
 * Get the comment config for a specific context, with optional groupId and eventId.
 * - For feed context with groupId: Returns specialized config for group posts in feed
 * - For groups context: Requires groupId, returns specialized config with groupId baked in
 * - For events context: Requires eventId, returns specialized config with eventId baked in
 * - For other contexts: Returns the base config
 */
export const getCommentConfig = (
  context: string,
  groupId?: string,
  eventId?: number,
): CommentConfig => {
  const builder = commentConfigBuilders[context];
  if (!builder) {
    throw new Error(`No configuration found for comment context: ${context}`);
  }
  return builder(groupId, eventId);
};
