/*
 * Copyright (C) 2022 Savoir-faire Linux Inc.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation; either version 3 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public
 * License along with this program.  If not, see
 * <https://www.gnu.org/licenses/>.
 */

import { Dialog, DialogProps, List, Stack, Typography } from '@mui/material';
import { IConversationRequest } from 'jami-web-common';
import { useCallback, useMemo } from 'react';
import { useTranslation } from 'react-i18next';
import { useNavigate } from 'react-router-dom';

import { useConversationDisplayNameShort } from '../hooks/useConversationDisplayName';
import { Contact } from '../models/contact';
import {
  useAcceptConversationRequestMutation,
  useBlockConversationRequestMutation,
  useConversationRequestsQuery,
  useDeclineConversationRequestMutation,
} from '../services/conversationQueries';
import { ColoredRoundButton } from './Button';
import ConversationAvatar from './ConversationAvatar';
import { CustomListItemButton } from './CustomListItemButton';
import { useDialogHandler } from './Dialog';
import LoadingPage from './Loading';
import { CheckMarkIcon, PersonWithCrossMarkIcon, SaltireIcon } from './SvgIcon';

export const ConversationRequestList = () => {
  const conversationRequestsQuery = useConversationRequestsQuery();
  const conversationRequests = conversationRequestsQuery.data;

  return (
    <List>
      {conversationRequests?.map((conversationRequest) => (
        <ConversationRequestListItem
          key={conversationRequest.conversationId}
          conversationRequest={conversationRequest}
        />
      ))}
    </List>
  );
};

type ConversationRequestListItemProps = {
  conversationRequest: IConversationRequest;
};

const ConversationRequestListItem = ({ conversationRequest }: ConversationRequestListItemProps) => {
  const dialogHandler = useDialogHandler();
  const infos = conversationRequest.infos;

  const conversationName = useConversationDisplayNameShort(null, infos.title, conversationRequest.membersNames);

  return (
    <>
      <HandleConversationRequestDialog {...dialogHandler.props} conversationRequest={conversationRequest} />
      <CustomListItemButton
        onClick={dialogHandler.openDialog}
        icon={<ConversationAvatar displayName={conversationName} src={infos.avatar} />}
        primaryText={<Typography variant="body1">{conversationName}</Typography>}
      />
    </>
  );
};

type HandleConversationRequestDialogProps = DialogProps & {
  conversationRequest: IConversationRequest;
};

const HandleConversationRequestDialog = ({ conversationRequest, ...props }: HandleConversationRequestDialogProps) => {
  const { t } = useTranslation();
  const navigate = useNavigate();

  const {
    conversationId,
    infos: { avatar, title },
  } = conversationRequest;

  const contact = useMemo(() => {
    return new Contact(conversationRequest.from.uri, conversationRequest.from.registeredName);
  }, [conversationRequest]);

  const closeDialog = useCallback(
    () => props.onClose?.({}, 'escapeKeyDown'), // dummy arguments
    [props]
  );

  const blockConversationRequestMutation = useBlockConversationRequestMutation();
  const acceptConversationRequestMutation = useAcceptConversationRequestMutation();
  const declineConversationRequestMutation = useDeclineConversationRequestMutation();

  const blockConversationRequest = useCallback(() => {
    blockConversationRequestMutation.mutate(
      { conversationId },
      {
        onSettled: closeDialog,
      }
    );
  }, [blockConversationRequestMutation, conversationId, closeDialog]);

  const acceptConversationRequest = useCallback(() => {
    acceptConversationRequestMutation.mutate(
      { conversationId },
      {
        onSuccess: () => navigate(`/conversation/${conversationId}`),
        onSettled: closeDialog,
      }
    );
  }, [acceptConversationRequestMutation, conversationId, closeDialog, navigate]);

  const declineConversationRequest = useCallback(() => {
    declineConversationRequestMutation.mutate(
      { conversationId },
      {
        onSettled: closeDialog,
      }
    );
  }, [declineConversationRequestMutation, conversationId, closeDialog]);

  return (
    <Dialog {...props}>
      <Stack alignItems="center" spacing="40px" position="relative">
        <Typography variant="caption" visibility={acceptConversationRequestMutation.isLoading ? 'hidden' : 'visible'}>
          {t('conversation_request_has_sent_request', { contact: contact.getDisplayName() })}
        </Typography>
        <ConversationAvatar displayName={title} src={avatar} sx={{ width: '112px', height: '112px' }} />
        {acceptConversationRequestMutation.isLoading ? (
          <>
            <Typography variant="h3" whiteSpace="pre-line" textAlign="center" fontWeight="bold">
              {t('conversation_request_accepted')}
            </Typography>
            <Typography variant="caption" whiteSpace="pre-line" textAlign="center">
              {t('conversation_request_waiting_for_sync', { contact: contact.getDisplayName() })}
            </Typography>
            <LoadingPage />
          </>
        ) : (
          <>
            <Typography variant="h3" whiteSpace="pre-line" textAlign="center" fontWeight="bold">
              {t('conversation_request_ask_join')}
            </Typography>
            <Stack direction="row" spacing="30px">
              <ColoredRoundButton
                aria-label="block conversation"
                onClick={blockConversationRequest}
                Icon={PersonWithCrossMarkIcon}
                paletteColor={(theme) => theme.palette.warning}
              />
              <ColoredRoundButton
                aria-label="decline conversation request"
                onClick={declineConversationRequest}
                Icon={SaltireIcon}
                paletteColor={(theme) => theme.palette.error}
              />
              <ColoredRoundButton
                aria-label="accept conversation request"
                onClick={acceptConversationRequest}
                Icon={CheckMarkIcon}
                paletteColor={(theme) => theme.palette.success}
              />
            </Stack>
          </>
        )}
      </Stack>
    </Dialog>
  );
};
