import { type FC, useMemo } from 'react';
import { useQuery } from 'react-query';

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 { NavigationAction } from 'src/constants/navigationActions';
import useGeneralError from 'src/hooks/useGeneralError';
import useHuGoTheme from 'src/hooks/useHuGoTheme';
import { useTriggerNavigationAction } from 'src/hooks/useNavigationAction';
import {
  setGroupFeedDetailData,
  setGroupFeedListData,
} from 'src/pages/dashboard/groups/queries';
import { getGif } from 'src/services/attachments';
import { requestGroupPostEdition, updateGroupPost } from 'src/services/groups';
import { EventName } from 'src/types/amplitude';
import { type Links } from 'src/types/actionLinks';
import { FileTypes } from 'src/types/attachments';
import { type GroupPost, GroupPostStates } from 'src/types/groups';
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 {
  getPollDeadlineValidationErrorKey,
  getPollEditWithVotesErrorKey,
} from 'src/utils/poll';

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

import { useGroupMember } from '../GroupMemberContext';
import { groupsRoutes } from '../routes';

import GroupPostAddForm from './GroupPostAddForm';

export type GroupPostEditCardProps = Pick<
  GroupPost,
  | 'id'
  | 'body'
  | 'bodyHtml'
  | 'bodyAttributes'
  | 'linkPreviews'
  | 'attachments'
  | 'state'
  | 'poll'
  | 'metadata'
> & {
  groupId: string;
  onSuccess?: () => void;
  displayCancelButton?: boolean;
  _links?: Links;
};

const GroupPostEditCard: FC<GroupPostEditCardProps> = props => {
  const {
    id,
    body,
    bodyHtml,
    bodyAttributes = [],
    linkPreviews,
    attachments = [],
    state,
    groupId,
    poll,
    metadata,
    onSuccess,
    displayCancelButton = true,
    _links,
  } = props;

  const { t } = useLokaliseTranslation(['post']);
  const showGeneralError = useGeneralError();
  const HugoThemeProvider = useHuGoTheme();
  const triggerNavigationAction = useTriggerNavigationAction();
  const { enqueueSnackbar } = useSnackbar();
  const { postsNeedApproval, isGroupAdmin } = useGroupMember();
  const actionLinks = extractActionLinks({ _links });
  const hasBackendActions = hasActionLinks(actionLinks);
  const shouldRequestEditionApprovalByPermissions =
    postsNeedApproval && !isGroupAdmin;
  // Backend is source of truth when `_links` are present.
  const shouldRequestEditionApproval =
    state === GroupPostStates.POSTED &&
    (hasBackendActions
      ? canPerformAnyAction(actionLinks, REQUEST_EDIT_ACTIONS)
      : shouldRequestEditionApprovalByPermissions);

  const handleSuccess = (post: GroupPost) => {
    logEvent(EventName.GROUPS_POST_UPDATED, {
      groupId: Number(groupId),
      postId: id,
    });
    if (shouldRequestEditionApproval) {
      enqueueSnackbar({
        title: t('post:changes_sent_for_review'),
        variant: 'success',
      });
      onSuccess?.();
      return;
    }
    setGroupFeedListData(post.id, groupId, post);
    setGroupFeedDetailData(post.id, groupId, post);
    onSuccess?.();
  };

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

  const { images, videos, files, audios, gifAttachment } = useMemo(
    () => ({
      images: attachments
        .filter(attachment => attachment.type === FileTypes.IMAGE)
        .map(getFormFileFromAttachment),
      videos: attachments
        .filter(attachment => attachment.type === FileTypes.VIDEO)
        .map(getFormFileFromAttachment),
      files: attachments
        .filter(attachment => attachment.type === FileTypes.FILE)
        .map(getFormFileFromAttachment),
      audios: attachments
        .filter(attachment => attachment.type === FileTypes.AUDIO)
        .map(getFormFileFromAttachment),
      gifAttachment: attachments.find(
        attachment => attachment.type === FileTypes.GIF,
      ),
    }),
    [attachments],
  );

  const gifId = gifAttachment?.externalReference?.id;

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

  const handleScheduledPostView = () => {
    triggerNavigationAction(
      groupsRoutes.detail(groupId),
      NavigationAction.OPEN_SCHEDULED_POSTS,
    );
  };

  return (
    <HugoThemeProvider>
      <HuCardContainer
        key={`${id}-${attachments.length}`}
        fullWidth
      >
        <GroupPostAddForm
          isEdit
          key={`${id}-${attachments.length}-${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}
          defaultGroupTitle={undefined}
          defaultDateTimeSchedule={undefined}
          state={state}
          poll={poll || undefined}
          request={newBody =>
            shouldRequestEditionApproval
              ? requestGroupPostEdition(
                  groupId,
                  id,
                  toContentOnlyEditRequestPayload(newBody, {
                    includeRequiredGroupFields: true,
                  }),
                ).then(response => ({
                  ...response,
                  data: (response.data?.groupPost ??
                    response.data) as GroupPost,
                }))
              : updateGroupPost(groupId, id, newBody)
          }
          onSuccess={handleSuccess}
          onError={handleError}
          displayCancelButton={displayCancelButton}
          isRequestingEditionApproval={shouldRequestEditionApproval}
          isGroups
          onScheduledPostView={handleScheduledPostView}
          embeddedSlot={
            withShareMetadata.isShare(metadata) ? (
              <SharedPost metadata={metadata} />
            ) : undefined
          }
        />
      </HuCardContainer>
    </HugoThemeProvider>
  );
};

export default GroupPostEditCard;
