'use client';

import { useAuth, useClerk } from '@clerk/nextjs';
import * as DropdownMenu from '@radix-ui/react-dropdown-menu';
import { useGateValue } from '@statsig/react-bindings';
import clsx from 'clsx';
import { EmojiClickData } from 'emoji-picker-react';
import { throttle } from 'lodash-es';
import { observer } from 'mobx-react-lite';
import { usePathname } from 'next/navigation';
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import { Trans, useTranslation } from 'react-i18next';
import { useInView } from 'react-intersection-observer';
import { twMerge } from 'tailwind-merge';

import { useStores } from '@/app/(root)/AppProviders';
import Button, {
  ButtonShape,
  ButtonSize,
  ButtonVariant,
} from '@/components/button/Button';
import { SkeletonText } from '@/components/layout/Skeleton';
import ListItem from '@/components/listView/ListItem';
import { useDialogModal } from '@/components/modal/DialogModal';
import CharacterCount from '@/components/textarea/CharacterCount';
import { useComments } from '@/hooks/useComments';
import useDeviceAttributes from '@/hooks/useDeviceAttributes';
import { CheckIcon, ChevronDownIcon, SortIcon } from '@/icons';
import logWebUserEvent from '@/logging/logWebUserEvent';
import { CommentEntityType, CommentSortBy } from '@/state/clipStore';
import {
  FALLBACK_IMAGE_URL,
  MENTION_CLEANUP_REGEX,
  SIGNUP_SOURCE_PARAM,
  SIGNUP_SOURCE_VALUES,
} from '@/utils/constants';
import { parseMentions } from '@/utils/mentions';
import { getClerkSignInRedirectProps } from '@/utils/utils';

import CommentEmojiPicker from './CommentEmojiPicker';
import CommentInput from './CommentInput';
import CommentListItem from './CommentListItem';
import CommentReportReasons from './CommentReportReasons';
import CommentSkeleton from './CommentSkeleton';
import CommentThread from './CommentThread';
import MentionSuggestions from './MentionSuggestions';
import MobileCommentsModal from './MobileCommentsModal';
import {
  COMMENT_MAX_LENGTH,
  COMMENT_MOST_LIKED_SORT_THRESHOLD,
  extractCurrentWord,
} from './utils';

const SHOW_LOGGED_OUT_COMMENT_INPUT = true;

export type Props = React.HTMLAttributes<HTMLDivElement> & {
  headerClassName?: string;
  bodyClassName?: string;
  entityId: string;
  entityType: CommentEntityType;
  allowComments?: boolean | null;
  numComments?: number;
  defaultSortBy?: CommentSortBy;
  autoPagination?: boolean;
  currentTime?: string;
  commentMaxLength?: number;
  isUserContentOwner?: boolean;
  autoFocus?: boolean;
  deeplinkedCommentId?: string;
  disablePortal?: boolean;
};

function getDefaultSortBy(numComments?: number) {
  return numComments != null && numComments < COMMENT_MOST_LIKED_SORT_THRESHOLD
    ? CommentSortBy.Newest
    : CommentSortBy.MostLiked;
}

const Comments: React.FC<Props> = observer((props) => {
  const {
    className,
    headerClassName,
    bodyClassName,
    allowComments: clipAllowComment,
    entityId,
    entityType,
    numComments: clipNumComments,
    defaultSortBy = getDefaultSortBy(clipNumComments),
    autoPagination = true,
    currentTime,
    commentMaxLength = COMMENT_MAX_LENGTH,
    isUserContentOwner = false,
    autoFocus = false,
    deeplinkedCommentId,
    disablePortal = false,
    ...restProps
  } = props;

  const { t } = useTranslation();
  const clerk = useClerk();
  const pathname = usePathname();

  // Mobile modal state
  const [showMobileModal, setShowMobileModal] = useState(false);

  const { session, clips: clipsStore, playbar: playbarStore } = useStores();

  // Get the clip data to check for creator information
  const clip =
    entityId && entityType === 'clip' ? clipsStore.clipById[entityId] : null;

  // Get parent clip data for remixes
  const [parentClipData, setParentClipData] = useState<any>(null);
  const parentClip =
    parentClipData?.id && entityType === 'clip'
      ? clipsStore.clipById[parentClipData.id]
      : null;

  useEffect(() => {
    const fetchParentClip = async () => {
      if (clip?.id) {
        const parent = await clipsStore.getParentClip(clip.id);
        setParentClipData(parent);
      } else {
        setParentClipData(null);
      }
    };

    fetchParentClip();
  }, [clip, clipsStore]);

  const [inputValue, setInputValue] = useState('');
  const [mentionQuery, setMentionQuery] = useState<string | null>(null);

  const stateRef = useRef({
    inputValue,
    mentionQuery,
    mentionSuggestion: {} as {
      handle: string | null;
      displayName: string | null;
      isExact: boolean;
    },
    mentionsUsedMap: new Map<string, string>(),
  });

  useEffect(() => {
    stateRef.current.inputValue = inputValue;
  }, [inputValue]);
  useEffect(() => {
    stateRef.current.mentionQuery = mentionQuery;
  }, [mentionQuery]);

  const mentionCursorRef = useRef<[word: string, start: number, end: number]>([
    '',
    0,
    0,
  ]);
  const commentInputRef = useRef<HTMLTextAreaElement>(null);
  const parseMention = useMemo(
    () =>
      throttle((value: string) => {
        stateRef.current.mentionSuggestion = {
          handle: null,
          displayName: null,
          isExact: false,
        };
        if (
          commentInputRef.current &&
          commentInputRef.current.selectionStart ===
            commentInputRef.current.selectionEnd
        ) {
          mentionCursorRef.current = extractCurrentWord(
            value,
            commentInputRef.current.selectionStart
          );
          const [currentWord] = mentionCursorRef.current;
          if (currentWord.startsWith('@')) {
            setMentionQuery(
              currentWord.replace(MENTION_CLEANUP_REGEX, '').slice(1)
            );
          } else {
            setMentionQuery(null);
          }
        }
      }, 250),
    []
  );
  // @TODO: This would probably be less janky if it was done on keyup
  useEffect(() => {
    parseMention(inputValue);
  }, [inputValue, parseMention]);

  const handleSuggestion = useCallback(
    (handle: string, displayName: string) => {
      stateRef.current.mentionSuggestion = {
        handle,
        displayName,
        isExact: stateRef.current.mentionQuery === handle,
      };
    },
    []
  );

  const handleMentionSelect = useCallback(
    (handle: string, displayName: string) => {
      // Keep track of the mention we used so we can replace it later on
      stateRef.current.mentionsUsedMap.set(handle, displayName);

      const [currentWord, start, end] = mentionCursorRef.current;
      const replacementWord = currentWord.startsWith('@')
        ? `@${handle}`
        : handle;
      setInputValue((prevInputValue) =>
        [
          prevInputValue.slice(0, start),
          replacementWord,
          prevInputValue.slice(end),
        ].join('')
      );
      const cursorPosition = start + replacementWord.length;
      // Wait a frame
      setTimeout(() => {
        if (commentInputRef.current) {
          commentInputRef.current.focus();
          commentInputRef.current.setSelectionRange(
            cursorPosition,
            cursorPosition,
            'none'
          );
        }
        // Hide the suggestions
        setMentionQuery(null);
      }, 0);
    },
    []
  );

  const [sortBy, setSortBy] = useState(defaultSortBy);

  const {
    comments,
    numComments,
    allowComments: commentsAllowComment,
    disableCommentReason,
    updatedTime,
    query: commentsQuery,
    reactionMutation,
    commentMutation,
    deleteMutation,
    reportMutation,
    blockMutation,
    unblockMutation,
  } = useComments({
    entityId,
    entityType,
    sortBy,
    deeplinkedCommentId,
    refetchOnMount: 'always',
  });

  const { isMobile, isSmallScreen } = useDeviceAttributes();

  // Mobile modal state for this branch's feature
  const { isSignedIn } = useAuth();
  const enableLoggedInMobileSongPage = useGateValue('logged-in-song-page-v2');

  // Watch for modal open trigger from playbar store
  useEffect(() => {
    if (
      isMobile &&
      enableLoggedInMobileSongPage &&
      isSignedIn &&
      playbarStore.shouldOpenMobileCommentsModal
    ) {
      setShowMobileModal(true);
      playbarStore.resetMobileCommentsModalTrigger();
    }
  }, [
    isMobile,
    enableLoggedInMobileSongPage,
    isSignedIn,
    playbarStore.shouldOpenMobileCommentsModal,
    playbarStore,
  ]);

  const readonly = !isSignedIn;
  const allowComments =
    (!readonly || SHOW_LOGGED_OUT_COMMENT_INPUT) &&
    (clipAllowComment ?? commentsAllowComment);

  const { launchDialog } = useDialogModal();

  const handleLike = useCallback<
    NonNullable<React.ComponentProps<typeof CommentListItem>['onLike']>
  >(
    (payload) => {
      reactionMutation.mutate({
        commentId: payload.id,
        commentEntityType: payload.type,
        isLike: payload.like ?? true,
      });
    },
    [reactionMutation]
  );

  const handleDelete = useCallback<
    NonNullable<React.ComponentProps<typeof CommentListItem>['onDelete']>
  >(
    (payload) => {
      async function deleteComment() {
        const action = await launchDialog<boolean>(
          t('comments.confirmDelete'),
          [
            { label: t('cta.confirm'), action: true },
            { label: t('cta.cancel'), action: false },
          ]
        );
        if (action === true) {
          await deleteMutation.mutateAsync({
            commentId: payload.id,
            commentEntityType: payload.type,
          });
        }
      }
      deleteComment();
    },
    [deleteMutation, launchDialog, t]
  );

  const handleReport = useCallback<
    NonNullable<React.ComponentProps<typeof CommentListItem>['onReport']>
  >(
    (payload) => {
      async function reportComment() {
        let reason: string | undefined = undefined;
        const action = await launchDialog<boolean>(
          <CommentReportReasons
            defaultValue={reason}
            onChange={(nextReason) => {
              reason = nextReason;
            }}
          />,
          [
            { label: t('actions.report'), action: true },
            { label: t('cta.cancel'), action: false },
          ]
        );
        if (action === true) {
          await reportMutation.mutateAsync({
            commentId: payload.id,
            commentEntityType: payload.type,
            reason,
          });
        }
      }
      reportComment();
    },
    [reportMutation, launchDialog, t]
  );

  const handleBlock = useCallback<
    NonNullable<React.ComponentProps<typeof CommentListItem>['onBlock']>
  >(
    (payload) => {
      async function blockUser() {
        const action = await launchDialog<boolean>(
          <>
            <h4 className='text-base'>
              <Trans
                t={t}
                i18nKey={'comments.confirmBlockName'}
                values={{ name: payload.handle }}
                components={{ nameLink: <b /> }}
              />
            </h4>
            <p className='text-xs text-foreground-secondary'>
              {t('comments.confirmBlockBody')}
            </p>
          </>,
          [
            {
              label: payload.handle
                ? t('actions.blockName', { name: payload.handle })
                : t('actions.block'),
              action: true,
            },
            { label: t('cta.cancel'), action: false },
          ]
        );
        if (action === true) {
          await blockMutation.mutateAsync({
            handle: payload.handle,
            reason: payload.reason,
          });
        }
      }
      blockUser();
    },
    [blockMutation, launchDialog, t]
  );

  const handleUnblock = useCallback<
    NonNullable<React.ComponentProps<typeof CommentListItem>['onUnblock']>
  >(
    (payload) => {
      async function unblockUser() {
        const action = await launchDialog<boolean>(
          <Trans
            t={t}
            i18nKey={'comments.confirmUnblockName'}
            values={{ name: payload.handle }}
            components={{ nameLink: <b /> }}
          />,
          [
            {
              label: payload.handle
                ? t('actions.unblockName', { name: payload.handle })
                : t('actions.unblock'),
              action: true,
            },
            { label: t('cta.cancel'), action: false },
          ]
        );
        if (action === true) {
          await unblockMutation.mutateAsync({
            handle: payload.handle,
          });
        }
      }
      unblockUser();
    },
    [unblockMutation, launchDialog, t]
  );

  const [paginationRef] = useInView({
    onChange: async (inView) => {
      if (inView && !commentsQuery.isFetchingNextPage) {
        commentsQuery.fetchNextPage();
      }
    },
  });

  const handleLoadMoreClick = useCallback(() => {
    commentsQuery.fetchNextPage();
  }, [commentsQuery]);

  const handleEmojiClick = useCallback((emojiData: EmojiClickData) => {
    setInputValue((prevValue) => prevValue + emojiData.emoji);
  }, []);

  const handleInputChange = useCallback((_e: any, value: string) => {
    setInputValue(value);
  }, []);

  const handleKeyDown = useCallback(
    (e: React.KeyboardEvent<HTMLTextAreaElement>) => {
      switch (true) {
        case e.key === 'Escape':
          setMentionQuery(null);
          break;
        case e.key === 'Tab' && !!stateRef.current.mentionSuggestion.handle:
          const { handle, displayName } = stateRef.current.mentionSuggestion;

          // Keep track of the mention we used so we can replace it later on
          stateRef.current.mentionsUsedMap.set(
            handle,
            displayName || `@${handle}`
          );

          const [currentWord, start, end] = mentionCursorRef.current;
          const replacementWord = currentWord.startsWith('@')
            ? `@${handle}`
            : handle;
          setInputValue((prevInputValue) =>
            [
              prevInputValue.slice(0, start),
              replacementWord,
              ' ', // Add a space after the suggestion
              prevInputValue.slice(end),
            ].join('')
          );
          const cursorPosition = start + replacementWord.length + 1;
          // Wait a frame
          setTimeout(() => {
            if (commentInputRef.current) {
              commentInputRef.current.focus();
              commentInputRef.current.setSelectionRange(
                cursorPosition,
                cursorPosition,
                'none'
              );
            }
            // Hide the suggestions
            setMentionQuery(null);
          }, 0);
          e.preventDefault();
          break;
        default:
          break;
      }
    },
    []
  );

  const handleSend = useCallback(() => {
    async function sendComment() {
      await commentMutation.mutateAsync({
        content: parseMentions(
          stateRef.current.inputValue,
          stateRef.current.mentionsUsedMap
        ),
        trackTimestamp:
          playbarStore.clip?.id === entityId
            ? playbarStore.getCurrentTime() || null
            : null,
      });
      setInputValue('');
    }
    // NO BLANK COMMENTS ALLOWED!
    if (stateRef.current.inputValue.trim()) {
      sendComment();
    }
  }, [entityId, commentMutation, playbarStore]);

  // Logged out user and we don't expect to have any comments to show
  if (
    !(session.userId || SHOW_LOGGED_OUT_COMMENT_INPUT) &&
    allowComments === false &&
    !comments.length &&
    (!clipNumComments || commentsQuery.isFetched)
  ) {
    return null;
  }

  // Show mobile modal on mobile devices for logged-in users with feature flag enabled
  if (isMobile && enableLoggedInMobileSongPage && isSignedIn) {
    return (
      <>
        <MobileCommentsModal
          isOpen={showMobileModal}
          onClose={() => setShowMobileModal(false)}
          clipId={entityId}
          allowComments={allowComments}
          numComments={numComments}
          isUserContentOwner={isUserContentOwner}
          deeplinkedCommentId={deeplinkedCommentId}
          entityType={entityType}
        />

        {/* Hidden trigger - will be opened from SongPage */}
        <div style={{ display: 'none' }} data-mobile-comments-trigger />
      </>
    );
  }

  return (
    <div className={className} {...restProps}>
      {!(
        session.userId || SHOW_LOGGED_OUT_COMMENT_INPUT
      ) ? null : allowComments === false ? (
        <p
          className={twMerge(
            'px-4 pt-4 text-center text-foreground-inactive italic',
            headerClassName
          )}
        >
          {disableCommentReason || t('comments.disabledStateBody')}
        </p>
      ) : (
        <div className={twMerge('px-4', headerClassName)}>
          <CommentEmojiPicker
            onEmojiClick={handleEmojiClick}
            allowExpandReactions={!isMobile && !isSmallScreen}
            disablePortal={disablePortal}
          />
          <div className='relative'>
            <CommentInput
              avatarSrc={
                session.userId
                  ? session.user?.avatar_image_url
                  : FALLBACK_IMAGE_URL
              }
              value={inputValue}
              placeholder={t('comments.placeholder')}
              onChange={handleInputChange}
              onKeyDown={handleKeyDown}
              onSend={handleSend}
              onFocus={(e) => {
                if (!session.userId) {
                  logWebUserEvent({
                    actionName: 'CommentsOnSongPageSignUpPrompt',
                    context: {
                      entityId,
                      entityType,
                      numComments,
                    },
                  });
                  clerk.openSignIn({
                    withSignUp: true,
                    ...getClerkSignInRedirectProps(
                      `${pathname}?${SIGNUP_SOURCE_PARAM}=${SIGNUP_SOURCE_VALUES.SONG_PAGE}`
                    ),
                  });
                  e.preventDefault();
                  e.currentTarget.blur();
                }
              }}
              disabled={allowComments !== true || commentMutation.isPending}
              maxLength={commentMaxLength}
              autoFocus={autoFocus}
              ref={commentInputRef}
            />
            {commentMaxLength > 0 && (
              <CharacterCount
                className='px-4 py-1 text-right'
                okayClassName='text-foreground-inactive'
                length={inputValue.length}
                maxLength={commentMaxLength}
                visibleThreshold={0.7}
                warningThreshold={0.95}
              />
            )}
            <MentionSuggestions
              className='absolute inset-x-0 top-[calc(100%-1rem)]'
              query={mentionQuery}
              onSelect={handleMentionSelect}
              onSuggestion={handleSuggestion}
            />
          </div>
        </div>
      )}
      <div className={bodyClassName}>
        {allowComments === false &&
        !comments.length &&
        commentsQuery.isFetched ? null : !commentsQuery.isFetched ? (
          <div className='[--skeleton-bg:var(--color-background-fog-thick)]'>
            <div className='flex flex-row items-center justify-between px-4 pb-0.5'>
              <SkeletonText className='w-full max-w-[96px] rounded-full text-[28px] leading-normal' />
              <SkeletonText className='mx-2 w-full max-w-[72px] rounded-full' />
            </div>
            <CommentSkeleton />
            <CommentSkeleton />
          </div>
        ) : commentsQuery.isFetched && !comments.length ? (
          <div className='px-4 text-center'>
            <h4 className='font-serif text-[28px] leading-normal font-light text-foreground-primary'>
              {t('comments.emptyStateTitle')}
            </h4>
            {!isUserContentOwner && (
              <p className='text-foreground-inactive'>
                {t('comments.emptyStateBody')}
              </p>
            )}
          </div>
        ) : (
          <>
            <div className='flex flex-row items-center justify-between gap-2 px-4 py-2'>
              <h2 className='text-base font-medium text-foreground-primary'>
                {t('comments.numComments', { count: numComments })}
              </h2>
              <DropdownMenu.Root>
                <DropdownMenu.Trigger asChild>
                  <Button
                    className='cursor-pointer'
                    variant={ButtonVariant.Tertiary}
                    size={ButtonSize.Mini}
                    iconEnd={SortIcon}
                  >
                    {t('comments.sortBy')}
                  </Button>
                </DropdownMenu.Trigger>
                {disablePortal ? (
                  <DropdownMenu.Content
                    align='end'
                    className={clsx(
                      'flex flex-col items-start justify-start gap-1 rounded-md border',
                      'z-10 min-w-[160px] overflow-clip py-1',
                      'md:box-shadow border-border-secondary bg-background-secondary text-foreground-secondary',
                      'font-sans text-sm font-medium'
                    )}
                  >
                    <DropdownMenu.Item
                      onSelect={() => setSortBy(CommentSortBy.Newest)}
                      asChild
                    >
                      <Button
                        className='w-full'
                        contentClassName='w-full justify-between'
                        iconEnd={
                          sortBy === CommentSortBy.Newest
                            ? CheckIcon
                            : undefined
                        }
                        variant={ButtonVariant.Tertiary}
                        shape={ButtonShape.Rectangle}
                        size={ButtonSize.Mini}
                      >
                        {t('comments.recent')}
                      </Button>
                    </DropdownMenu.Item>
                    <DropdownMenu.Item
                      onSelect={() => setSortBy(CommentSortBy.Oldest)}
                      asChild
                    >
                      <Button
                        className='w-full'
                        contentClassName='w-full justify-between'
                        iconEnd={
                          sortBy === CommentSortBy.Oldest
                            ? CheckIcon
                            : undefined
                        }
                        variant={ButtonVariant.Tertiary}
                        shape={ButtonShape.Rectangle}
                        size={ButtonSize.Mini}
                      >
                        {t('comments.oldest')}
                      </Button>
                    </DropdownMenu.Item>
                    <DropdownMenu.Item
                      onSelect={() => setSortBy(CommentSortBy.MostLiked)}
                      asChild
                    >
                      <Button
                        className='w-full'
                        contentClassName='w-full justify-between'
                        iconEnd={
                          sortBy === CommentSortBy.MostLiked
                            ? CheckIcon
                            : undefined
                        }
                        variant={ButtonVariant.Tertiary}
                        shape={ButtonShape.Rectangle}
                        size={ButtonSize.Mini}
                      >
                        {t('comments.liked')}
                      </Button>
                    </DropdownMenu.Item>
                  </DropdownMenu.Content>
                ) : (
                  <DropdownMenu.Portal>
                    <DropdownMenu.Content
                      align='end'
                      className={clsx(
                        'flex flex-col items-start justify-start gap-1 rounded-md border',
                        'z-10 min-w-[160px] overflow-clip py-1',
                        'md:box-shadow border-border-secondary bg-background-secondary text-foreground-secondary',
                        'font-sans text-sm font-medium'
                      )}
                    >
                      <DropdownMenu.Item
                        onSelect={() => setSortBy(CommentSortBy.Newest)}
                        asChild
                      >
                        <Button
                          className='w-full'
                          contentClassName='w-full justify-between'
                          iconEnd={
                            sortBy === CommentSortBy.Newest
                              ? CheckIcon
                              : undefined
                          }
                          variant={ButtonVariant.Tertiary}
                          shape={ButtonShape.Rectangle}
                          size={ButtonSize.Mini}
                        >
                          {t('comments.recent')}
                        </Button>
                      </DropdownMenu.Item>
                      <DropdownMenu.Item
                        onSelect={() => setSortBy(CommentSortBy.Oldest)}
                        asChild
                      >
                        <Button
                          className='w-full'
                          contentClassName='w-full justify-between'
                          iconEnd={
                            sortBy === CommentSortBy.Oldest
                              ? CheckIcon
                              : undefined
                          }
                          variant={ButtonVariant.Tertiary}
                          shape={ButtonShape.Rectangle}
                          size={ButtonSize.Mini}
                        >
                          {t('comments.oldest')}
                        </Button>
                      </DropdownMenu.Item>
                      <DropdownMenu.Item
                        onSelect={() => setSortBy(CommentSortBy.MostLiked)}
                        asChild
                      >
                        <Button
                          className='w-full'
                          contentClassName='w-full justify-between'
                          iconEnd={
                            sortBy === CommentSortBy.MostLiked
                              ? CheckIcon
                              : undefined
                          }
                          variant={ButtonVariant.Tertiary}
                          shape={ButtonShape.Rectangle}
                          size={ButtonSize.Mini}
                        >
                          {t('comments.liked')}
                        </Button>
                      </DropdownMenu.Item>
                    </DropdownMenu.Content>
                  </DropdownMenu.Portal>
                )}
              </DropdownMenu.Root>
            </div>
            {comments.map((comment) => (
              <CommentThread
                key={comment.id}
                readonly={readonly}
                currentUserId={session.userId || undefined}
                avatarSrc={
                  session.userId
                    ? session.user?.avatar_image_url
                    : FALLBACK_IMAGE_URL
                }
                comment={comment}
                replies={comment.replies}
                hasMoreReplies={!!comment.replyContinuationToken}
                allowComments={allowComments}
                autoPagination={false}
                defaultShowAllReplies={false}
                onLike={handleLike}
                onModeratorDelete={session.isStaff ? handleDelete : undefined}
                onDelete={
                  isUserContentOwner || comment.userId === session.userId
                    ? handleDelete
                    : undefined
                }
                onReport={
                  comment.userId === session.userId ? undefined : handleReport
                }
                onBlock={
                  !isUserContentOwner ||
                  comment.userCommentsBlocked ||
                  comment.userId === session.userId
                    ? undefined
                    : handleBlock
                }
                onUnblock={
                  !isUserContentOwner ||
                  !comment.userCommentsBlocked ||
                  comment.userId === session.userId
                    ? undefined
                    : handleUnblock
                }
                currentTime={updatedTime}
                commentMaxLength={commentMaxLength}
                isUserContentOwner={isUserContentOwner}
                clipCreatorId={clip?.user_id || undefined}
                originalClipCreatorId={parentClip?.user_id || undefined}
                deeplinkedCommentId={deeplinkedCommentId}
                entityId={entityId}
                entityType={entityType}
                disablePortal={disablePortal}
              />
            ))}
            {commentsQuery.isFetchingNextPage && <CommentSkeleton />}
            {!commentsQuery.hasNextPage ||
            commentsQuery.isFetchingNextPage ? null : autoPagination ? (
              <div className='h-10' ref={paginationRef} />
            ) : (
              <ListItem className='ml-12 border-none pl-10 text-xs'>
                <button
                  className='flex flex-row items-center gap-1 text-sm font-medium text-foreground-secondary hover:underline'
                  onClick={handleLoadMoreClick}
                >
                  <span>{t('actions.showMore')}</span>
                  {<ChevronDownIcon className='h-3 w-3 text-current' />}
                </button>
              </ListItem>
            )}
          </>
        )}
      </div>
    </div>
  );
});

export default Comments;
