// Copyright 2025 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
import React, { memo, useCallback, type ReactNode } from 'react';
import { useSelector } from 'react-redux';
import { LinkPreviewItem } from '../../components/conversation/media-gallery/LinkPreviewItem.dom.tsx';
import { MediaGridItem } from '../../components/conversation/media-gallery/MediaGridItem.dom.tsx';
import { DocumentListItem } from '../../components/conversation/media-gallery/DocumentListItem.dom.tsx';
import { ContactListItem } from '../../components/conversation/media-gallery/ContactListItem.dom.tsx';
import { AudioListItem } from '../../components/conversation/media-gallery/AudioListItem.dom.tsx';
import type { ItemClickEvent } from '../../components/conversation/media-gallery/types/ItemClickEvent.std.ts';
import { getSafeDomain } from '../../types/LinkPreview.std.ts';
import type { GenericMediaItemType } from '../../types/MediaItem.std.ts';
import type { AttachmentStatusType } from '../../hooks/useAttachmentStatus.std.ts';
import { missingCaseError } from '../../util/missingCaseError.std.ts';
import { isVoiceMessagePlayed } from '../../util/isVoiceMessagePlayed.std.ts';
import {
  getIntl,
  getTheme,
  getUserConversationId,
} from '../selectors/user.std.ts';
import { getConversationSelector } from '../selectors/conversations.dom.ts';
import { getMediaGalleryState } from '../selectors/mediaGallery.std.ts';
import { useConversationsActions } from '../ducks/conversations.preload.ts';
import { SmartMediaContextMenu } from './MediaContextMenu.preload.tsx';

export type PropsType = Readonly<{
  onItemClick: (event: ItemClickEvent) => unknown;
  mediaItem: GenericMediaItemType;
}>;

function renderContextMenu(
  mediaItem: GenericMediaItemType,
  children: ReactNode
): React.JSX.Element {
  return (
    <SmartMediaContextMenu mediaItem={mediaItem}>
      {children}
    </SmartMediaContextMenu>
  );
}

export const MediaItem = memo(function MediaItem({
  mediaItem,
  onItemClick,
}: PropsType) {
  const i18n = useSelector(getIntl);
  const theme = useSelector(getTheme);
  const ourConversationId = useSelector(getUserConversationId);
  const getConversation = useSelector(getConversationSelector);
  const { sortOrder } = useSelector(getMediaGalleryState);

  const { showConversation } = useConversationsActions();

  const { message } = mediaItem;

  const authorTitle =
    message.type === 'outgoing'
      ? i18n('icu:you')
      : getConversation(message.sourceServiceId ?? message.source).title;

  const showMessage = useCallback(() => {
    showConversation({
      conversationId: message.conversationId,
      messageId: message.id,
    });
  }, [message.conversationId, message.id, showConversation]);

  const onClick = useCallback(
    (state: AttachmentStatusType['state']) => {
      onItemClick({ mediaItem, state });
    },
    [mediaItem, onItemClick]
  );

  const showSize = sortOrder === 'size';

  switch (mediaItem.type) {
    case 'audio':
      return (
        <AudioListItem
          i18n={i18n}
          authorTitle={authorTitle}
          isPlayed={isVoiceMessagePlayed(mediaItem.message, ourConversationId)}
          mediaItem={mediaItem}
          onClick={onClick}
          showMessage={showMessage}
          renderContextMenu={renderContextMenu}
        />
      );
    case 'media':
      return (
        <MediaGridItem
          mediaItem={mediaItem}
          showSize={showSize}
          onClick={onClick}
          renderContextMenu={renderContextMenu}
          i18n={i18n}
          theme={theme}
        />
      );
    case 'document':
      return (
        <DocumentListItem
          i18n={i18n}
          authorTitle={authorTitle}
          mediaItem={mediaItem}
          onClick={onClick}
          showMessage={showMessage}
          renderContextMenu={renderContextMenu}
        />
      );
    case 'contact':
      return (
        <ContactListItem
          i18n={i18n}
          authorTitle={authorTitle}
          mediaItem={mediaItem}
          onClick={onClick}
          showMessage={showMessage}
          renderContextMenu={renderContextMenu}
        />
      );
    case 'link': {
      const hydratedMediaItem = {
        ...mediaItem,
        preview: {
          ...mediaItem.preview,
          domain: getSafeDomain(mediaItem.preview.url),
        },
      };

      return (
        <LinkPreviewItem
          i18n={i18n}
          theme={theme}
          authorTitle={authorTitle}
          mediaItem={hydratedMediaItem}
          onClick={onClick}
          showMessage={showMessage}
          renderContextMenu={renderContextMenu}
        />
      );
    }
    default:
      throw missingCaseError(mediaItem);
  }
});
