import React, {memo, useCallback, useMemo} from 'react';
import {View, TouchableOpacity, Pressable} from 'react-native';
import {useTranslation} from 'react-i18next';
import {shallowEqual} from 'react-redux';
import {GifPreview} from '@components';
import MultimediaContainer from '@components/MultimediaContainer';
import LinkPreviewCard from '@components/_custom/LinkPreviewCard';
import TextWithLinks from '@components/TextWithLinks';
import {HtmlRender} from '@components/_custom/HtmlRender';
import PostTranslation from '@components/Post/components/PostBody/components/PostTranslation';
import {Typography} from '@components/_core';
import {LinkPreview} from '@interfaces/linkPreview';
import {
  AttachmentType,
  GifAttachment,
  Attachment,
} from '@interfaces/attachments';
import {extractTextFromHtml} from '@modules/post/screens/PublishPost/utils';
import {PreviewLivestreamVideo} from '@modules/livestream/components/PreviewLivestreamVideo';
import {FullPost, Post} from '@modules/post/interfaces';
import {useAppSelector} from '@redux/utils';
import {copyToClipboard, getHtmlToRender} from '@shared/utils';
import {Opacity} from '@shared/constants';
import {useTheme} from '@shared/theme';
import {useCommunityFeature} from '@stores/communityFeatures';

import PostPoll from './components/PostPoll';
import PostComment from './components/PostComment';
import {styles} from './styles';
import PostReactions from './components/PostReactions';
import {IMAGE_CONTAINER_WIDTH} from './constants';
import {checkHasPoll, getPostBodyGifProps} from './utils';
import {PostBodyProps} from './interfaces';
import Documents from './components/Documents';

function PostBody({
  onPress,
  isComment,
  isOwner,
  croppedBody,
  truncatedHtml,
  bodySizeLimit,
  normalBodyLimit,
  collapsedByDefault,
  canInteract = true,
  showCollapsedMedia,
  textShown,
  post,
  postId,
  reactions,
  handleReaction,
  onReactionPickerPress,
  toggleNumberOfLines,
  displayLastComment,
  isPinned,
  groupId,
  isMarketplace,
  articleId,
  parentId,
  onTagPress,
  showComments = true,
  showReactions = true,
  onPressComment,
  onCommentReactionPress,
  isArchived,
}: PostBodyProps) {
  const {
    id,
    body,
    bodyAttributes,
    attachments,
    poll,
    linkPreviews,
    stream,
    bodyHtml,
    languageCode,
  } = post as Post;
  const {t} = useTranslation();
  const {theme} = useTheme();
  const [
    canCommentGeneral,
    canCommentInPosts,
    canCommentInMarketplace,
    canCommentInArticles,
    canReactGeneral,
    canReactInPosts,
    canReactInMarketplace,
    canReactInArticles,
    userPostTranslationLanguage,
  ] = useAppSelector(
    ({user: {permissions, postTranslationLanguage}}) => [
      permissions.CREATE_COMMENT,
      permissions.CREATE_COMMENT_IN_POSTS,
      permissions.CREATE_COMMENT_IN_MARKETPLACE,
      permissions.CREATE_COMMENT_IN_ARTICLES,
      permissions.CAN_REACT_CONTENT,
      permissions.CAN_REACT_POSTS,
      permissions.CAN_REACT_MARKETPLACE_POSTS,
      permissions.CAN_REACT_ARTICLES,
      postTranslationLanguage,
    ],
    shallowEqual,
  );

  const canTranslate = useCommunityFeature('TRANSLATE_POSTS');

  const canComment =
    canCommentGeneral ||
    (isMarketplace && canCommentInMarketplace) ||
    (articleId && canCommentInArticles) ||
    (!isMarketplace && !articleId && canCommentInPosts);

  const canReact =
    canReactGeneral ||
    (isMarketplace && canReactInMarketplace) ||
    (articleId && canReactInArticles) ||
    (!isMarketplace && !articleId && canReactInPosts);

  const hasPoll = checkHasPoll(poll);
  const multimediaAttachments = useMemo(() => {
    return attachments?.filter(
      attachment =>
        ![AttachmentType.FILE, AttachmentType.GIF].includes(attachment.type),
    );
  }, [attachments]);
  const linkPreview = useMemo(() => {
    if (
      !linkPreviews ||
      !Object.values(linkPreviews)?.length ||
      !Object.values(linkPreviews)?.at(0)
    ) {
      return undefined;
    }
    return {
      ...Object.values(linkPreviews)[0],
      url: Object.keys(linkPreviews)[0],
    } as LinkPreview & {url: string};
  }, [linkPreviews]);
  const html = useMemo(
    () =>
      bodyHtml
        ? getHtmlToRender(
            !bodySizeLimit || textShown || showCollapsedMedia
              ? bodyHtml
              : truncatedHtml.htmlTruncated,
          )
        : '',
    [
      bodyHtml,
      bodySizeLimit,
      showCollapsedMedia,
      textShown,
      truncatedHtml.htmlTruncated,
    ],
  );

  const onLongPress = useCallback(() => {
    !!(html || croppedBody) &&
      copyToClipboard({
        text: html ? extractTextFromHtml(html).plainText : croppedBody,
      });
  }, [croppedBody, html]);

  const allowTranslation =
    !isMarketplace &&
    body?.length > 0 &&
    canTranslate &&
    languageCode &&
    userPostTranslationLanguage &&
    languageCode !== userPostTranslationLanguage;

  const reactionsAreShown = (!!groupId || canReact) && showReactions;

  return (
    <Pressable onPress={onPress} style={styles.container}>
      {!!(bodyHtml || body) && (
        <>
          <Pressable onPress={onPress} onLongPress={onLongPress}>
            <View style={styles.paragraphsContainer}>
              {bodyHtml ? (
                <View style={styles.htmlRenderContainer}>
                  <HtmlRender html={html} />
                </View>
              ) : (
                <TextWithLinks
                  value={croppedBody}
                  attributes={bodyAttributes}
                  onTagPress={onTagPress}
                />
              )}
              {bodySizeLimit &&
                ((bodyHtml
                  ? truncatedHtml.isTruncated
                  : body.length >= normalBodyLimit) ||
                  collapsedByDefault) && (
                  <View style={styles.seeMoreContainer}>
                    <Pressable onPress={toggleNumberOfLines}>
                      <Typography
                        variant="xs"
                        weight="semiBold"
                        color={theme.primaryText}>
                        {t(
                          showCollapsedMedia || textShown
                            ? 'post.see_less'
                            : 'post.see_more',
                        )}
                      </Typography>
                    </Pressable>
                  </View>
                )}
            </View>
          </Pressable>
          {!!linkPreview && (!isPinned || (isPinned && showCollapsedMedia)) && (
            <LinkPreviewCard data={linkPreview} />
          )}
        </>
      )}
      {((!bodyHtml && !body && multimediaAttachments?.length > 0) ||
        !collapsedByDefault ||
        showCollapsedMedia) && (
        <>
          {/* The empty TouchableOpacity function is in order to
          capture the event and avoid navigating to the PostDetail
          whenever the user PinchToZoom an image. (ANDROID BUG) */}
          <TouchableOpacity activeOpacity={Opacity.FULL}>
            {stream && !multimediaAttachments.length ? (
              <PreviewLivestreamVideo
                stream={stream}
                postId={id}
                groupId={groupId}
              />
            ) : (
              <MultimediaContainer
                attachments={multimediaAttachments as Attachment[]}
                {...(isComment && {width: IMAGE_CONTAINER_WIDTH})}
                postId={id}
                isComment={isComment}
                withAutoPlay
                imageProps={{resizeMode: 'contain'}}
              />
            )}
          </TouchableOpacity>
          <Documents
            files={
              attachments?.filter(
                a => a.type === AttachmentType.FILE,
              ) as Attachment[]
            }
          />
          {hasPoll && (
            <PostPoll
              canInteract={!!canInteract}
              groupId={groupId}
              poll={poll}
              postId={post.id}
            />
          )}
          {attachments?.some(a => a.type === AttachmentType.GIF) && (
            <GifPreview
              gif={attachments[0]?.externalReference}
              {...getPostBodyGifProps(
                attachments[0] as GifAttachment,
                isComment,
              )}
            />
          )}
          {allowTranslation && (
            <PostTranslation postId={post.id} groupId={groupId} />
          )}
          {reactionsAreShown && (
            <PostReactions
              reactions={reactions}
              isComment={isComment}
              post={post}
              postId={postId}
              groupId={groupId}
              disabled={isArchived || !canInteract}
              handleReaction={handleReaction}
              onReactionPickerPress={onReactionPickerPress}
              isMarketplace={isMarketplace}
              articleId={articleId}
              parentId={parentId}
            />
          )}
          {!isComment &&
            ((post as FullPost)?.commentsEnabled && showComments ? (
              <PostComment
                canComment={canComment}
                post={post as FullPost}
                postId={postId}
                displayLastComment={displayLastComment}
                isMarketplace={isMarketplace}
                groupId={groupId}
                canAnsweredComment={canInteract}
                handleOnPressComments={onPressComment}
                onReactionPress={onCommentReactionPress}
                isArchived={isArchived}
              />
            ) : (
              isOwner && (
                <View
                  style={[
                    styles.disabledComments,
                    {borderColor: theme.neutralDivider},
                  ]}>
                  <Typography variant="xs" color={theme.neutralTextLighter}>
                    {t('post.comments_disabled')}
                  </Typography>
                </View>
              )
            ))}
        </>
      )}
    </Pressable>
  );
}

export default memo(PostBody);
