import { FC } from 'react';
import { useMutation } from 'react-query';

import CardHeader from '@material-hu/mui/CardHeader';
import Stack from '@material-hu/mui/Stack';
import Tooltip from '@material-hu/mui/Tooltip';
import Typography from '@material-hu/mui/Typography';

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

import { MAX_NAME_LENGTH } from 'src/constants/posts';
import { useAuth } from 'src/contexts/JWTContext';
import { usePostAttachments } from 'src/hooks/usePostAttachments';
import {
  invalidateFeedScheduledPostList,
  postCreated,
} from 'src/pages/dashboard/feed/queries';
import GroupPostMenu from 'src/pages/dashboard/groups/components/GroupPostMenu';
import { invalidateGroupScheduledPostList } from 'src/pages/dashboard/groups/queries';
import { rescheduleGroupPost } from 'src/services/groups';
import {
  publishPublicationNow,
  updatePostPublicationDateTime,
} from 'src/services/posts';
import { ApprovalStatus, GroupSchedulePost } from 'src/types/groups';
import { Post } from 'src/types/posts';
import { getCompletedDate, getTimeFormat } from 'src/utils/date';
import { canApprovePosts, isPostApprovalRequested } from 'src/utils/feed';
import { useLokaliseTranslation as useTranslation } from 'src/utils/i18n';
import { truncateText } from 'src/utils/text';
import { getFullName } from 'src/utils/userUtils';

import { PostCardFeatures } from 'src/components/post/PostCardFeatures';
import TimeDistance from 'src/components/time/TimeDistance';
import { UserNameLink } from 'src/components/UserNameLink';
import ProfilePicture from 'src/components/user/ProfilePicture';

import PostMenu from '../PostMenu';

export type SchedulePostProps = {
  post: Post | GroupSchedulePost;
  onCloseModal: () => void;
};

const SchedulePost: FC<SchedulePostProps> = props => {
  const { post, onCloseModal } = props;

  const { t } = useTranslation('post');
  const { enqueueSnackbar } = useHuSnackbar();
  const { user, permissions } = useAuth();

  // Type guard to check if post is a GroupSchedulePost
  const isGroupPost = (
    _post: Post | GroupSchedulePost,
  ): _post is GroupSchedulePost => {
    return 'groupId' in _post && !!(_post as GroupSchedulePost).groupId;
  };

  const { mediaList, fileList, audioList, gif } = usePostAttachments(
    post.attachments ?? [],
  );

  const publishPostNow = useMutation(() => publishPublicationNow(post.id), {
    onSuccess: () => {
      if (isGroupPost(post)) {
        invalidateGroupScheduledPostList(post.groupId);
      } else {
        postCreated();
        invalidateFeedScheduledPostList();
      }
      onCloseModal();
      enqueueSnackbar({
        title: t('send_post_now_success'),
        variant: 'success',
      });
    },
    onError: () => {
      enqueueSnackbar({
        title: t('send_post_now_error'),
        variant: 'error',
      });
    },
  });

  const updatePostNow = useMutation(
    ({
      publicationDateTime,
      sendNotification,
    }: {
      publicationDateTime: Date;
      sendNotification: boolean;
    }) => {
      if (isGroupPost(post)) {
        return rescheduleGroupPost(
          post.id,
          post.groupId,
          publicationDateTime,
          sendNotification,
        );
      }
      // Changing push notification is not supported for feed posts
      return updatePostPublicationDateTime(post.id, {
        publicationDatetime: publicationDateTime,
      });
    },
    {
      onSuccess: () => {
        if (isGroupPost(post)) {
          invalidateGroupScheduledPostList(post.groupId);
        } else {
          invalidateFeedScheduledPostList();
        }
        enqueueSnackbar({
          title: t('reschedule_success'),
          variant: 'success',
        });
      },
      onError: () => {
        enqueueSnackbar({
          title: t('update_date_time_error'),
          variant: 'error',
        });
      },
    },
  );

  if (!user) {
    return null;
  }

  const handlePublishPostNow = () => publishPostNow.mutate();

  const reschedulePost = (
    publicationDateTime: string | Date,
    sendNotification: boolean,
  ) => {
    updatePostNow.mutate({
      publicationDateTime: new Date(publicationDateTime),
      sendNotification,
    });
  };

  const canEdit =
    canApprovePosts(permissions) || !isPostApprovalRequested(permissions);
  const canPostNow = post.approvalStatus === ApprovalStatus.APPROVED;

  // TODO: should use UnifiedPostCard
  return (
    <HuCardContainer
      id={`post-card-${post.id}`}
      sx={{ p: 1, mb: 2 }}
      fullWidth
    >
      <CardHeader
        sx={{
          '& .MuiCardHeader-avatar': {
            mr: 1,
          },
          p: 0,
          pb: 2,
        }}
        avatar={
          <ProfilePicture
            id={user.id}
            user={user}
          />
        }
        subheader={
          <Stack sx={{ flexDirection: 'row', alignItems: 'center' }}>
            <TimeDistance
              typographySx={{
                variant: 'globalXS',
                fontWeight: 'regular',
              }}
              date={new Date(post.publicationDatetime)}
              showIcon={false}
            />
          </Stack>
        }
        title={
          <Stack
            sx={{
              flexDirection: 'row',
              alignItems: 'center',
              WebkitLineClamp: 2,
              WebkitBoxOrient: 'vertical',
              overflow: 'hidden',
            }}
          >
            <Tooltip
              title={
                getFullName(user).length > MAX_NAME_LENGTH
                  ? getFullName(user)
                  : ''
              }
            >
              <UserNameLink
                user={user}
                displayName={truncateText(getFullName(user), MAX_NAME_LENGTH)}
              />
            </Tooltip>
          </Stack>
        }
        action={
          isGroupPost(post) ? (
            <GroupPostMenu
              id={post.id}
              user={user}
              isPinned={false}
              isKeyUpdate={false}
              isPendingApproval={post.approvalStatus === ApprovalStatus.PENDING}
              isSegmented={false}
              isSchedulePost
              publicationDatetime={post.publicationDatetime}
              reschedulePost={reschedulePost}
            />
          ) : (
            <PostMenu
              id={post.id}
              user={user}
              canEdit={canEdit}
              isGroupPost={{
                value: !!post.group,
                groupId: post.group?.id || 0,
              }}
              isPendingApproval={post.approvalStatus === ApprovalStatus.PENDING}
              isKeyUpdate={false}
              isSegmented={false}
              isSchedulePost
              publicationDatetime={post.publicationDatetime}
              reschedulePost={reschedulePost}
              handlePublishPostNow={handlePublishPostNow}
              canPostNow={canPostNow}
            />
          )
        }
      />
      <Typography
        variant="globalS"
        style={{
          lineHeight: '1.4em',
          height: '2.8em',
          overflow: 'hidden',
          textOverflow: 'ellipsis',
          display: '-webkit-box',
          WebkitLineClamp: 2,
          WebkitBoxOrient: 'vertical',
        }}
      >
        {post.body}
      </Typography>

      <PostCardFeatures
        id={post.id}
        poll={post.poll}
        gif={gif}
        mediaList={mediaList}
        fileList={fileList}
        audioList={audioList}
        linkPreviews={post.linkPreviews}
        grantVideoDownload={true}
        userCanVote={false}
      />

      <Typography variant="globalXS">
        <Stack sx={{ mt: 2 }} />
        {t('post_publish_description', {
          date: getCompletedDate(post.publicationDatetime, user),
          time: getTimeFormat(post.publicationDatetime),
        })}
      </Typography>
    </HuCardContainer>
  );
};

export default SchedulePost;
