import {
  Attachment,
  AttachmentType,
  GifAttachment,
  RequestAttachment,
} from '@interfaces/attachments';
import {Poll} from '@interfaces/poll';
import {User} from '@interfaces/user';
import {SegmentationUserSection} from '@interfaces/segmentation';
import {Post} from '@modules/post/interfaces';
import {extractTextFromHtml, transformSpansToLinks} from '@modules/post/utils';
import {
  getCompleteName,
  getGifDimensions,
  getGifProps,
  normalizeAccents,
  sizeToBytes,
} from '@shared/utils';
import {GIPHY, windowDimensions} from '@shared/constants';

import {AttachmentsData, DraftState} from './interfaces';
import {GIF_WIDTH} from './constants';
import {AuthorData} from './components/Author';

export function getPostAttachments(post?: Partial<Post>): AttachmentsData {
  const defaultAttachments = {
    attachmentsSize: 0,
    initialImages: [],
    images: [],
    initialVideos: [],
    videos: [],
    initialFiles: [],
    files: [],
    initialGif: null,
    gif: null,
  };

  if (!post?.attachments || !Array.isArray(post.attachments)) {
    return defaultAttachments;
  }

  return post.attachments.reduce(
    (attachmentsData: AttachmentsData, attachment: RequestAttachment) => {
      const typedAttachment = attachment as Attachment;
      switch (attachment.type) {
        case AttachmentType.IMAGE:
          attachmentsData.images.push(typedAttachment);
          attachmentsData.initialImages.push(typedAttachment);
          break;
        case AttachmentType.VIDEO:
          attachmentsData.videos.push(typedAttachment);
          attachmentsData.initialVideos.push(typedAttachment);
          break;
        case AttachmentType.FILE:
          attachmentsData.files.push(typedAttachment);
          attachmentsData.initialFiles.push(typedAttachment);
          break;
        case AttachmentType.GIF: {
          const gifAtt = attachment as GifAttachment;
          const refId = attachment.externalReference?.id;
          const giphyId = typeof gifAtt.id === 'string' ? gifAtt.id : undefined;
          const resolvedId = refId ?? giphyId;
          if (!resolvedId) {
            break;
          }
          const id = String(resolvedId);
          attachmentsData.gif = {...gifAtt, id};
          attachmentsData.initialGif = {...gifAtt, id};
          break;
        }
      }
      attachmentsData.attachmentsSize += sizeToBytes(attachment.size);
      return attachmentsData;
    },
    defaultAttachments,
  );
}

const DEFAULT_ASPECT_RATIO = 1;
const POST_WIDTH = windowDimensions.width;
const POST_HEIGHT = windowDimensions.height * 0.3;

export const getPostBodyGifProps = (
  attachment: GifAttachment,
  isComment?: boolean,
) => {
  const aspectRatio =
    attachment?.width && attachment?.height
      ? attachment.width / attachment.height
      : DEFAULT_ASPECT_RATIO;
  return getGifProps({
    aspectRatio,
    maxHeight: POST_HEIGHT,
    maxWidth: isComment ? GIF_WIDTH : POST_WIDTH,
  });
};

export const checkHasPoll = (poll: Nullable<Poll>): poll is Poll =>
  !!poll?.pollOptions?.length;

const CODE_TAG_REGEX = /<code>/g;
const CODE_CLOSE_TAG_REGEX = /<\/code>/g;
export const getHtmlToRender = (html: string) =>
  html
    .replace(CODE_TAG_REGEX, '<code>&nbsp;')
    .replace(CODE_CLOSE_TAG_REGEX, '&nbsp;</code>');
export const userToAuthor = (
  user: Pick<User, 'id' | 'profilePicture' | 'firstName' | 'lastName'>,
) =>
  ({
    id: user.id,
    name: getCompleteName(user),
    avatarUrl: user.profilePicture,
  } as AuthorData);

export const segmentateUsers = (users: User[]): SegmentationUserSection[] => {
  const sections: Record<string, SegmentationUserSection> = {};

  users.forEach(user => {
    const firstChar = normalizeAccents(user.firstName.charAt(0).toUpperCase());

    if (!sections[firstChar]) {
      sections[firstChar] = {title: firstChar, data: [user]};
    } else {
      sections[firstChar].data.push(user);
    }
  });

  return Object.values(sections);
};

export const buildDraft = (state: DraftState): Partial<Post> => {
  const bodyHtml = state.messageBody
    ? transformSpansToLinks(state.messageBody)
    : '';
  const body = bodyHtml ? extractTextFromHtml(bodyHtml).plainText : '';

  return {
    body,
    bodyHtml,
    bodyAttributes: state.taggedUsers,
    linkPreviews: state.linkPreviews ?? undefined,
    segmentationItemIdsArray: state.segmentationItemIds,
    attachments: [
      ...state.images,
      ...state.videos,
      ...state.files,
      ...(state.gif
        ? [
            {
              type: AttachmentType.GIF,
              externalReference: {id: `${state.gif.id}`, origin: GIPHY},
              ...getGifDimensions(state.gif),
            } as RequestAttachment,
          ]
        : []),
    ],
    poll: state.hasPoll
      ? ({
          pollOptions: state.pollOptions.map(option => ({option})),
          pollConfiguration: state.pollConfiguration,
        } as Poll)
      : null,
  };
};
