import { type FC, Suspense, useMemo } from 'react';
import { FormProvider } from 'react-hook-form';
import { useNavigate } from 'react-router';

import ImageIcon from '@material-hu/icons/material/Image';
import { IconAccessPoint } from '@material-hu/icons/tabler';
import Box from '@material-hu/mui/Box';
import CircularProgress from '@material-hu/mui/CircularProgress';
import Skeleton from '@material-hu/mui/Skeleton';
import Stack from '@material-hu/mui/Stack';
import Typography from '@material-hu/mui/Typography';

import Alert from '@material-hu/components/design-system/Alert';
import Button from '@material-hu/components/design-system/Buttons/Button';

import { logEvent } from 'src/config/amplitude';
import { useAuth } from 'src/contexts/JWTContext';
import { usePosts } from 'src/contexts/PostContext';
import usePermissions from 'src/hooks/usePermissions';
import usePosting, { type GenericUsePostingProps } from 'src/hooks/usePosting';
import useRequiredParams from 'src/hooks/useRequiredParams';
import PreviewLinkCard from 'src/pages/dashboard/feed/components/PreviewLinkCard';
import {
  PollAdd,
  PollReadOnly,
  usePollDrawer,
} from 'src/pages/dashboard/feed/components/poll';
import { EventName } from 'src/types/amplitude';
import { type PollState } from 'src/types/feed';
import { type GroupPost } from 'src/types/groups';
import { StreamDestination } from 'src/types/stream';
import { bytesFrom } from 'src/utils/bytes';
import { buildPostDraftKey, readComposerDraft } from 'src/utils/composerDrafts';
import {
  getEditionPublishText,
  getNonTextReadOnlySx,
} from 'src/utils/editionApproval';
import { useLokaliseTranslation as useTranslation } from 'src/utils/i18n';
import { lazyRetry } from 'src/utils/lazyRetry';
import { UserPermissions } from 'src/utils/permissions';

import {
  AttachmentsAdd,
  AttachmentsList,
  AttachmentsSize,
} from 'src/components/attachment';
import ErrorDialog from 'src/components/dialogs/ErrorDialog';
import { LoadingButton } from 'src/components/LoadingButton';
import LoggedUserAvatar from 'src/components/LoggedUserAvatar';

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

import GroupSchedulePost from './GroupSchedulePost';

const RichTextEditor = lazyRetry(() => import('src/components/RichTextEditor'));

type GroupPostAddFormProps = GenericUsePostingProps<GroupPost> & {
  displayCancelButton?: boolean;
  isRequestingEditionApproval?: boolean;
  /** Slot rendered after the rich-text editor and before the attachments list (used by share-post). */
  embeddedSlot?: React.ReactNode;
};

const { CREATE_LIVESTREAM, VIEW_LIVESTREAM } = UserPermissions;

const GroupPostAddForm: FC<GroupPostAddFormProps> = props => {
  const {
    displayCancelButton = true,
    isRequestingEditionApproval: isRequestingEditionApprovalOverride,
    embeddedSlot,
    ...usePostingProps
  } = props;
  const { isEdit = false, defaultBodyHtml = '' } = usePostingProps;

  const { id: groupId } = useRequiredParams(['id']);
  const navigate = useNavigate();
  const { t } = useTranslation(['group']);
  const { user: loggedUser, instance: authInstance } = useAuth();
  const { isGroupAdmin, userCanPost, postsNeedApproval } = useGroupMember();
  const draftKey =
    loggedUser && authInstance
      ? buildPostDraftKey({
          scope: 'groups',
          instanceId: authInstance.id,
          userId: loggedUser.id,
          groupId,
        })
      : null;
  const initialComposerContent = useMemo(() => {
    if (isEdit || !draftKey) {
      return defaultBodyHtml;
    }

    return readComposerDraft(draftKey) || defaultBodyHtml;
  }, [isEdit, draftKey, defaultBodyHtml]);

  const {
    instance,
    user,
    openError,
    closeErrorDialog,
    form,
    handleSubmit,
    submit,
    imagesAttach,
    filesAttach,
    videosAttach,
    audiosAttach,
    isSubmitting,
    showPreviewLink,
    urls,
    metadata,
    isLoadingPreviewLink,
    handleRemovePreviewLink,
    hasAttachments,
    gif,
    handleDelete,
    handleRemoveGif,
    withPoll,
    setWithPoll,
    handlePollUpdate,
    pollOptionsForEdit,
    pollState,
    canRemovePoll,
    handleAddFiles,
    handleAddGif,
    handleAddMultimedia,
    attachmentsDisabled,
    images,
    videos,
    files,
    handleEditCancel,
    openCancelDialog,
    setOpenCancelDialog,
    handleOnDiscard,
    disabledSubmitButton,
    handleChangePositionMultimedia,
    handlePaste,
    pollVotersVisible,
    handlePollVotersVisibilityChange,
    pollDeadlineEnabled,
    pollEndsAt,
    handlePollDeadlineChange,
    handleCheckNotificationAndSubmit,
    notificationAlertModal,
    handleSchedulePost,
    shouldClearPollWhenCancelling,
  } = usePosting<GroupPost>({
    ...usePostingProps,
    showScheduledPostsViewButton: isGroupAdmin || !postsNeedApproval,
    draftKey,
    defaultSendNotification:
      !isEdit && !isGroupAdmin ? true : usePostingProps.defaultSendNotification,
  });
  const { isGroupsPosting } = usePosts();

  const { hasAll: canCreateLiveStream } = usePermissions([
    CREATE_LIVESTREAM,
    VIEW_LIVESTREAM,
  ]);

  const onSchedulePost = (date: string, sendNotification: boolean) => {
    handleSchedulePost(new Date(date), isGroupAdmin ? sendNotification : true);
  };

  const onPublishClick = () => {
    if (!isGroupAdmin) {
      form.setValue('sendNotification', true);
    }
    handleCheckNotificationAndSubmit(isGroupAdmin);
  };

  const isPostGroupsSubmitting = isSubmitting || isGroupsPosting;
  const isButtonFeedDisabled = disabledSubmitButton || isGroupsPosting;
  const isRequestingEditionApproval =
    isRequestingEditionApprovalOverride ?? false;
  const nonTextReadOnlySx = getNonTextReadOnlySx(isRequestingEditionApproval);

  const pollDrawerState = useMemo((): PollState => {
    if (!isRequestingEditionApproval || pollState.form.disabled) {
      return pollState;
    }
    return {
      form: { disabled: true, message: '' },
      cancel: { disabled: true, message: '' },
    };
  }, [isRequestingEditionApproval, pollState]);

  const getPublishText = () =>
    getEditionPublishText({
      t,
      isSubmitting: isPostGroupsSubmitting,
      isEdit,
      isRequestingEditionApproval,
    });

  const goToLiveStream = () => {
    navigate(groupsRoutes.liveStream(groupId));
    logEvent(EventName.LIVESTREAM_SETUP_STARTED, {
      userId: user?.id,
      destination: StreamDestination.GROUPS,
      destinationID: groupId,
    });
  };

  const showLiveStreamButton =
    instance?.allowLiveStream ||
    (canCreateLiveStream &&
      (isGroupAdmin || (userCanPost && !postsNeedApproval)));

  const { drawer: pollCreateDrawer, showDrawer: showPollDrawer } =
    usePollDrawer({
      withPoll,
      // polls can always be added in groups
      canAddPoll: true,
      isSubmitting: isPostGroupsSubmitting,
      pollState: pollDrawerState,
      pollOptionsForEdit,
      pollVotersVisible,
      isEdit,
      onPollUpdate: handlePollUpdate,
      onPollVotersVisibilityChange: handlePollVotersVisibilityChange,
      pollDeadlineEnabled,
      pollEndsAt,
      onPollDeadlineChange: handlePollDeadlineChange,
      setWithPoll,
      shouldClearPollWhenCancelling,
    });

  return (
    <>
      <ErrorDialog
        open={openError}
        onAccept={closeErrorDialog}
        message={t('post:error_max_attachments_size')}
      />
      <FormProvider {...form}>
        <form
          noValidate
          onSubmit={handleSubmit(submit)}
        >
          <Box>
            <Box
              sx={{
                display: { xs: 'block', sm: 'flex' },
                justifyContent: 'space-between',
                alignItems: 'center',
              }}
            >
              <LoggedUserAvatar showPill={false} />
              <Stack
                sx={{
                  flexDirection: 'row',
                  alignItems: 'center',
                  gap: 1,
                }}
              ></Stack>
              <AttachmentsSize
                sx={{ ml: 1 }}
                images={imagesAttach}
                files={filesAttach}
                videos={videosAttach}
                audios={audiosAttach}
                maxBytes={bytesFrom(instance?.maxPostSizeInMB ?? 0, 'MB')}
                addPost
              />
            </Box>
            <Suspense
              fallback={
                <Skeleton
                  height={60}
                  width="100%"
                />
              }
            >
              <RichTextEditor
                name="bodyHtml"
                content={initialComposerContent}
                isEdit={isEdit}
                handlePaste={handlePaste}
                disabled={isPostGroupsSubmitting}
              />
            </Suspense>
            {showPreviewLink && (
              <PreviewLinkCard
                linkPreviews={{ [urls[0]]: metadata?.data }}
                isLoading={isLoadingPreviewLink}
                onRemove={handleRemovePreviewLink}
              />
            )}
            {embeddedSlot && <Box sx={{ mt: 1.5, mb: 1 }}>{embeddedSlot}</Box>}
            {hasAttachments && (
              <Box sx={nonTextReadOnlySx}>
                <AttachmentsList
                  sx={{ my: 0.5 }}
                  gif={gif}
                  images={imagesAttach}
                  files={filesAttach}
                  videos={videosAttach}
                  audios={audiosAttach}
                  onDelete={
                    isRequestingEditionApproval ? undefined : handleDelete
                  }
                  onRemoveGif={
                    isRequestingEditionApproval ? undefined : handleRemoveGif
                  }
                  disabled={
                    isPostGroupsSubmitting || isRequestingEditionApproval
                  }
                  isPost
                  handleChangePositionMultimedia={
                    handleChangePositionMultimedia
                  }
                />
              </Box>
            )}

            {/* Show read-only poll when poll options exist */}
            {withPoll &&
              pollOptionsForEdit.length > 0 &&
              pollOptionsForEdit.some(option => option.trim()) && (
                <PollReadOnly
                  options={pollOptionsForEdit.filter(option => option.trim())}
                  onEdit={
                    isRequestingEditionApproval
                      ? undefined
                      : () => showPollDrawer({})
                  }
                  onRemove={
                    canRemovePoll && !isRequestingEditionApproval
                      ? () => {
                          handlePollUpdate([]);
                          setWithPoll(false);
                        }
                      : undefined
                  }
                />
              )}

            {isRequestingEditionApproval && (
              <Alert
                severity="info"
                title={t('post:send_for_review')}
                description={t('post:edited_version_pending_approval')}
                sx={{ mt: 2, mb: 1.5 }}
              />
            )}

            <CancelPostEditionAlert
              open={openCancelDialog}
              onClose={() => setOpenCancelDialog(false)}
              onDiscard={handleOnDiscard}
            />

            <Stack
              sx={{
                flexDirection: 'row',
                justifyContent: 'space-between',
                alignItems: 'center',
                width: '100%',
                pt: { xs: 1, sm: 1.5 },
              }}
            >
              <Stack
                sx={{
                  flexDirection: 'row',
                  justifyContent: 'start',
                  alignItems: 'center',
                  flexWrap: 'wrap',
                  color: theme => theme.palette.new.text.neutral.default,
                }}
              >
                {!isRequestingEditionApproval && (
                  <AttachmentsAdd
                    onAddMultipleFiles={handleAddFiles}
                    onAddGif={handleAddGif}
                    onAddMultimedia={handleAddMultimedia}
                    gifDisabled={hasAttachments || withPoll}
                    disabled={attachmentsDisabled}
                    multimediaSize={images.length + videos.length}
                    filesSize={files.length}
                    iconCustomPhoto={<ImageIcon />}
                    checkMax={false}
                    direction="bottom"
                  />
                )}
                {!isRequestingEditionApproval && (
                  <PollAdd
                    onAdd={() => setWithPoll(true)}
                    disabled={withPoll || !!gif || isPostGroupsSubmitting}
                    sx={{ color: 'primary.main' }}
                  />
                )}
              </Stack>
              <Stack
                sx={{
                  flexDirection: {
                    xs: isRequestingEditionApproval ? 'column' : 'row',
                    sm: 'row',
                  },
                  justifyContent: 'flex-end',
                  alignItems: {
                    xs: isRequestingEditionApproval ? 'stretch' : 'center',
                    sm: 'center',
                  },
                  gap: isRequestingEditionApproval ? 1 : 0,
                }}
              >
                {isEdit && displayCancelButton && (
                  <Button
                    disabled={isPostGroupsSubmitting}
                    onClick={handleEditCancel}
                    variant="outlined"
                    type="button"
                    sx={{
                      py: 1.5,
                      height: '100%',
                      width: {
                        xs: isRequestingEditionApproval ? '100%' : 'auto',
                        sm: 'auto',
                      },
                    }}
                  >
                    <Typography
                      variant="globalS"
                      fontWeight={'fontWeightSemiBold'}
                      color={theme => theme.palette.new.text.neutral.brand}
                    >
                      {t('general:cancel')}
                    </Typography>
                  </Button>
                )}
                {!isEdit && (
                  <Stack
                    sx={{
                      gap: 1,
                      flexDirection: 'row',
                      alignItems: 'stretch',
                      alignSelf: 'stretch',
                    }}
                  >
                    {showLiveStreamButton && (
                      <Button
                        startIcon={<IconAccessPoint />}
                        variant="secondary"
                        sx={{
                          py: 1.5,
                          gap: 0.5,
                          height: '100%',
                        }}
                        onClick={goToLiveStream}
                      >
                        <Typography
                          variant="globalS"
                          fontWeight="fontWeightSemiBold"
                          color={theme => theme.palette.new.text.neutral.brand}
                        >
                          {t('post:transmit')}
                        </Typography>
                      </Button>
                    )}
                    <GroupSchedulePost
                      onSchedulePost={onSchedulePost}
                      disabled={isButtonFeedDisabled || isPostGroupsSubmitting}
                    />
                  </Stack>
                )}
                <LoadingButton
                  variant="contained"
                  onClick={onPublishClick}
                  loadingIndicator={
                    <CircularProgress
                      size={16}
                      color="inherit"
                      sx={{ my: 0.5 }}
                    />
                  }
                  loading={isPostGroupsSubmitting}
                  disabled={isButtonFeedDisabled}
                  sx={{
                    ml: isRequestingEditionApproval ? { xs: 0, sm: 1 } : 1,
                    px: 2,
                    py: 1.5,
                    height: '100%',
                    width: {
                      xs: isRequestingEditionApproval ? '100%' : 'auto',
                      sm: 'auto',
                    },
                    '&.Mui-disabled': {
                      backgroundColor: theme =>
                        isPostGroupsSubmitting
                          ? theme.palette.new.action.button.background.primary
                              .default
                          : undefined,
                      color: isPostGroupsSubmitting ? 'white' : undefined,
                    },
                  }}
                >
                  <Typography
                    variant="globalS"
                    fontWeight={'fontWeightSemiBold'}
                    color="white"
                  >
                    {getPublishText()}
                  </Typography>
                </LoadingButton>
              </Stack>
            </Stack>
          </Box>
        </form>
        {pollCreateDrawer}
      </FormProvider>
      {notificationAlertModal}
    </>
  );
};

export default GroupPostAddForm;
