import { type FC } from 'react';
import { useQuery } from 'react-query';
import { useNavigate } from 'react-router-dom';

import HuCardContainer from '@material-hu/components/design-system/CardContainer';
import useSnackbar from '@material-hu/components/design-system/Snackbar';

import { logEvent } from 'src/config/logging';
import useGeneralError from 'src/hooks/useGeneralError';
import useHuGoTheme from 'src/hooks/useHuGoTheme';
import usePermissions from 'src/hooks/usePermissions';
import PostAddForm from 'src/pages/dashboard/feed/components/PostAddForm';
import {
  setFeedDetailData,
  setFeedListData,
} from 'src/pages/dashboard/feed/queries';
import { feedRoutes } from 'src/pages/dashboard/feed/routes';
import { getGif } from 'src/services/attachments';
import { requestFeedPostEdition, updatePost } from 'src/services/posts';
import { EventName } from 'src/types/amplitude';
import { type Links } from 'src/types/actionLinks';
import { FileTypes } from 'src/types/attachments';
import { PostState } from 'src/types/feed';
import { type Post, type PostData } from 'src/types/posts';
import { withShareMetadata } from 'src/utils/sharedPost';
import {
  canPerformAnyAction,
  extractActionLinks,
  hasActionLinks,
  REQUEST_EDIT_ACTIONS,
} from 'src/utils/actionsLinks';
import { checkAndShowError } from 'src/utils/errorHandlers';
import { generateHTMLFromText } from 'src/utils/feed';
import { getFormFileFromAttachment } from 'src/utils/files';
import { useLokaliseTranslation } from 'src/utils/i18n';
import { toContentOnlyEditRequestPayload } from 'src/utils/postEditRequest';
import { UserPermissions } from 'src/utils/permissions';
import {
  getPollDeadlineValidationErrorKey,
  getPollEditWithVotesErrorKey,
} from 'src/utils/poll';

import { attachmentKeys } from 'src/components/attachment/queries';
import { SharedPost } from 'src/components/post/SharedPost';

export type PostEditCardProps = Pick<
  Post,
  | 'id'
  | 'body'
  | 'bodyHtml'
  | 'bodyAttributes'
  | 'linkPreviews'
  | 'attachments'
  | 'hasBeenSegmented'
  | 'state'
  | 'segmentation'
  | 'isKeyUpdate'
  | 'poll'
  | 'metadata'
> & {
  _links?: Links;
};

const PostEditCard: FC<PostEditCardProps> = props => {
  const {
    id,
    body,
    bodyHtml,
    bodyAttributes,
    linkPreviews,
    attachments,
    hasBeenSegmented,
    state,
    segmentation,
    isKeyUpdate,
    poll,
    metadata,
    _links,
  } = props;

  const { t } = useLokaliseTranslation();
  const showGeneralError = useGeneralError();
  const navigate = useNavigate();
  const HugoThemeProvider = useHuGoTheme();
  const { enqueueSnackbar } = useSnackbar();
  const { hasAll: postNeedApproval } = usePermissions([
    UserPermissions.REQUEST_FEED_POST_APPROVAL,
  ]);
  const { hasAll: canApproveFeedPosts } = usePermissions([
    UserPermissions.CAN_APPROVE_FEED_POSTS,
  ]);
  const actionLinks = extractActionLinks({ _links });
  const hasBackendActions = hasActionLinks(actionLinks);
  const shouldRequestEditionApprovalByPermissions =
    postNeedApproval && !canApproveFeedPosts;
  // Backend is source of truth when `_links` are present.
  const shouldRequestEditionApproval =
    state === PostState.POSTED &&
    (hasBackendActions
      ? canPerformAnyAction(actionLinks, REQUEST_EDIT_ACTIONS)
      : shouldRequestEditionApprovalByPermissions);

  const handleSuccess = (post: Post) => {
    logEvent(EventName.POST_UPDATE, { postId: id });
    if (shouldRequestEditionApproval) {
      enqueueSnackbar({
        title: t('post:changes_sent_for_review'),
        variant: 'success',
      });
      navigate(-1);
      return;
    }
    setFeedListData(post.id, post);
    setFeedDetailData(post.id, post);
    if (state === PostState.SCHEDULED) {
      navigate(feedRoutes.feed(), { state: { id: 'schedulePost' } });
    } else {
      navigate(-1);
    }
  };

  const handleError = (error: any) => {
    checkAndShowError(error, showGeneralError, t, [
      getPollEditWithVotesErrorKey,
      getPollDeadlineValidationErrorKey,
    ]);
  };

  const images = attachments
    .filter(attachment => attachment.type === FileTypes.IMAGE)
    .map(getFormFileFromAttachment);

  const videos = attachments
    .filter(attachment => attachment.type === FileTypes.VIDEO)
    .map(getFormFileFromAttachment);

  const files = attachments
    .filter(attachment => attachment.type === FileTypes.FILE)
    .map(getFormFileFromAttachment);

  const audios = attachments
    .filter(attachment => attachment.type === FileTypes.AUDIO)
    .map(getFormFileFromAttachment);

  const gifAttachment = attachments.find(
    attachment => attachment.type === FileTypes.GIF,
  );

  const gifId = gifAttachment?.externalReference?.id;

  const { data: gif } = useQuery(
    attachmentKeys.gif(gifId!),
    () => getGif(gifId!),
    { enabled: !!gifId },
  );

  return (
    <HugoThemeProvider>
      <HuCardContainer
        fullWidth
        sx={{
          borderColor: theme =>
            hasBeenSegmented
              ? theme.palette.new.border.neutral.brand
              : theme.palette.new.border.neutral.default,
        }}
      >
        <PostAddForm
          isEdit
          key={gif?.data.id}
          defaultBodyHtml={
            bodyHtml || generateHTMLFromText(body, bodyAttributes ?? [])
          }
          {...(bodyAttributes && { deafultBodyAttributes: bodyAttributes })}
          defaultLinkPreviews={linkPreviews}
          defaultImages={images}
          {...(gif?.data && { defaultGif: gif.data })}
          defaultVideos={videos}
          defaultFiles={files}
          defaultAudios={audios}
          state={state}
          segmentation={segmentation}
          request={(newBody: PostData) =>
            shouldRequestEditionApproval
              ? requestFeedPostEdition(
                  id,
                  toContentOnlyEditRequestPayload(newBody),
                ).then(response => ({
                  ...response,
                  data: (response.data?.post ?? response.data) as Post,
                }))
              : updatePost(id, newBody)
          }
          onSuccess={handleSuccess}
          onError={handleError}
          isKeyUpdate={isKeyUpdate}
          poll={poll || undefined}
          isRequestingEditionApproval={shouldRequestEditionApproval}
          embeddedSlot={
            withShareMetadata.isShare(metadata) ? (
              <SharedPost metadata={metadata} />
            ) : undefined
          }
        />
      </HuCardContainer>
    </HugoThemeProvider>
  );
};

export default PostEditCard;
