/****************************************************************
 * Licensed to the Apache Software Foundation (ASF) under one   *
 * or more contributor license agreements.  See the NOTICE file *
 * distributed with this work for additional information        *
 * regarding copyright ownership.  The ASF licenses this file   *
 * to you under the Apache License, Version 2.0 (the            *
 * "License"); you may not use this file except in compliance   *
 * with the License.  You may obtain a copy of the License at   *
 *                                                              *
 *   http://www.apache.org/licenses/LICENSE-2.0                 *
 *                                                              *
 * Unless required by applicable law or agreed to in writing,   *
 * software distributed under the License is distributed on an  *
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
 * KIND, either express or implied.  See the License for the    *
 * specific language governing permissions and limitations      *
 * under the License.                                           *
 ****************************************************************/
package org.apache.james.jmap.draft.methods;

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doCallRealMethod;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;

import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;

import jakarta.mail.Flags;
import jakarta.mail.Flags.Flag;

import org.apache.commons.lang3.NotImplementedException;
import org.apache.james.core.Username;
import org.apache.james.jmap.draft.model.GetMessagesRequest;
import org.apache.james.jmap.draft.model.GetMessagesResponse;
import org.apache.james.jmap.methods.BlobManager;
import org.apache.james.jmap.methods.JmapResponse;
import org.apache.james.jmap.methods.Method;
import org.apache.james.jmap.model.MessageProperties.MessageProperty;
import org.apache.james.jmap.model.MethodCallId;
import org.apache.james.jmap.memory.projections.MemoryMessageFastViewProjection;
import org.apache.james.jmap.model.message.view.MessageFastViewFactory;
import org.apache.james.jmap.model.message.view.MessageFullView;
import org.apache.james.jmap.model.message.view.MessageFullViewFactory;
import org.apache.james.jmap.model.message.view.MessageHeaderView;
import org.apache.james.jmap.model.message.view.MessageHeaderViewFactory;
import org.apache.james.jmap.model.message.view.MessageMetadataView;
import org.apache.james.jmap.model.message.view.MessageMetadataViewFactory;
import org.apache.james.jmap.model.message.view.MetaMessageViewFactory;
import org.apache.james.jmap.utils.JsoupHtmlTextExtractor;
import org.apache.james.mailbox.FlagsBuilder;
import org.apache.james.mailbox.MailboxSession;
import org.apache.james.mailbox.MailboxSessionUtil;
import org.apache.james.mailbox.MessageIdManager;
import org.apache.james.mailbox.MessageManager;
import org.apache.james.mailbox.MessageManager.AppendCommand;
import org.apache.james.mailbox.inmemory.manager.InMemoryIntegrationResources;
import org.apache.james.mailbox.model.ComposedMessageId;
import org.apache.james.mailbox.model.MailboxId;
import org.apache.james.mailbox.model.MailboxPath;
import org.apache.james.mailbox.store.StoreMailboxManager;
import org.apache.james.metrics.logger.DefaultMetricFactory;
import org.apache.james.metrics.tests.RecordingMetricFactory;
import org.apache.james.mime4j.message.BodyPartBuilder;
import org.apache.james.mime4j.message.MultipartBuilder;
import org.apache.james.mime4j.stream.RawField;
import org.apache.james.util.html.HtmlTextExtractor;
import org.apache.james.util.mime.MessageContentExtractor;
import org.assertj.core.api.Condition;
import org.assertj.core.data.MapEntry;
import org.assertj.core.groups.Tuple;
import org.junit.Before;
import org.junit.Test;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ser.impl.SimpleBeanPropertyFilter;
import com.fasterxml.jackson.databind.ser.impl.SimpleFilterProvider;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Sets;
import com.jayway.jsonpath.JsonPath;

import reactor.core.publisher.Mono;

public class GetMessagesMethodTest {
    private static final String FORWARDED = "forwarded";
    private static final Username ROBERT = Username.of("robert");

    private MessageIdManager messageIdManager;
    private org.apache.james.mime4j.dom.Message messageContent1;
    private org.apache.james.mime4j.dom.Message messageContent2;
    private org.apache.james.mime4j.dom.Message messageContent3;
    private StoreMailboxManager mailboxManager;
    private GetMessagesMethod testee;
    private MailboxSession session;
    private MailboxPath inboxPath;
    private MailboxPath customMailboxPath;
    private MethodCallId methodCallId;
    private MessageMetadataViewFactory messageMetadataViewFactory;

    @Before
    public void setup() throws Exception {
        methodCallId = MethodCallId.of("#0");
        MessageContentExtractor messageContentExtractor = new MessageContentExtractor();
        HtmlTextExtractor htmlTextExtractor = new JsoupHtmlTextExtractor();
        BlobManager blobManager = mock(BlobManager.class);
        InMemoryIntegrationResources resources = InMemoryIntegrationResources.defaultResources();
        mailboxManager = resources.getMailboxManager();

        session = MailboxSessionUtil.create(ROBERT);
        inboxPath = MailboxPath.inbox(session);
        customMailboxPath = new MailboxPath(inboxPath, "custom");
        mailboxManager.createMailbox(inboxPath, session);
        mailboxManager.createMailbox(customMailboxPath, session);
        messageIdManager = resources.getMessageIdManager();

        messageMetadataViewFactory = spy(new MessageMetadataViewFactory(blobManager, messageIdManager));
        MessageFullViewFactory messageFullViewFactory = new MessageFullViewFactory(blobManager, messageContentExtractor,
            htmlTextExtractor, messageIdManager,
            new MemoryMessageFastViewProjection(new RecordingMetricFactory()));
        MessageFastViewFactory messageFastViewFactory = new MessageFastViewFactory(blobManager, messageIdManager,
            new MemoryMessageFastViewProjection(new RecordingMetricFactory()), messageFullViewFactory);

        MetaMessageViewFactory metaMessageViewFactory = new MetaMessageViewFactory(
            messageFullViewFactory,
            new MessageHeaderViewFactory(blobManager, messageIdManager),
            messageMetadataViewFactory,
            messageFastViewFactory);
        testee = new GetMessagesMethod(metaMessageViewFactory, new DefaultMetricFactory());

        messageContent1 = org.apache.james.mime4j.dom.Message.Builder.of()
            .setSubject("message 1 subject")
            .setBody("my message", StandardCharsets.UTF_8)
            .build();

        messageContent2 = org.apache.james.mime4j.dom.Message.Builder.of()
            .setSubject("message 2 subject")
            .setBody("my message", StandardCharsets.UTF_8)
            .build();

        messageContent3 = org.apache.james.mime4j.dom.Message.Builder.of()
            .addField(new RawField("Great-Header", "message 3 subject"))
            .setBody("my message", StandardCharsets.UTF_8)
            .build();
    }

    @Test
    public void processShouldThrowWhenNullRequest() {
        GetMessagesRequest request = null;
        assertThatThrownBy(() -> testee.processToStream(request, mock(MethodCallId.class), mock(MailboxSession.class))).isInstanceOf(NullPointerException.class);
    }

    @Test
    public void processShouldThrowWhenNullSession() {
        MailboxSession mailboxSession = null;
        assertThatThrownBy(() -> testee.processToStream(mock(GetMessagesRequest.class), mock(MethodCallId.class), mailboxSession)).isInstanceOf(NullPointerException.class);
    }

    @Test
    public void processShouldThrowWhenNullMethodCallId() {
        MethodCallId methodCallId = null;
        assertThatThrownBy(() -> testee.processToStream(mock(GetMessagesRequest.class), methodCallId, mock(MailboxSession.class))).isInstanceOf(NullPointerException.class);
    }

    @Test
    public void processShouldThrowWhenRequestHasAccountId() {
        assertThatThrownBy(() -> testee.processToStream(
            GetMessagesRequest.builder().accountId("abc").build(), mock(MethodCallId.class), mock(MailboxSession.class))).isInstanceOf(NotImplementedException.class);
    }

    @Test
    @SuppressWarnings("unchecked")
    public void processShouldFetchMessages() throws Exception {
        MessageManager inbox = mailboxManager.getMailbox(inboxPath, session);
        ComposedMessageId message1 = inbox.appendMessage(AppendCommand.from(messageContent1), session).getId();
        ComposedMessageId message2 = inbox.appendMessage(AppendCommand.from(messageContent2), session).getId();
        ComposedMessageId message3 = inbox.appendMessage(AppendCommand.from(messageContent3), session).getId();

        GetMessagesRequest request = GetMessagesRequest.builder()
            .ids(ImmutableList.of(message1.getMessageId(),
                message2.getMessageId(),
                message3.getMessageId()))
            .build();

        List<JmapResponse> result = testee.processToStream(request, methodCallId, session).collect(Collectors.toList());

        assertThat(result).hasSize(1)
            .extracting(JmapResponse::getResponse)
            .hasOnlyElementsOfType(GetMessagesResponse.class)
            .extracting(GetMessagesResponse.class::cast)
            .flatExtracting(GetMessagesResponse::list)
            .hasOnlyElementsOfType(MessageFullView.class)
            .extracting(MessageFullView.class::cast)
            .extracting(MessageFullView::getId, MessageFullView::getSubject, MessageFullView::getTextBody)
            .containsOnly(
                Tuple.tuple(message1.getMessageId(), "message 1 subject", Optional.of("my message")),
                Tuple.tuple(message2.getMessageId(), "message 2 subject", Optional.of("my message")),
                Tuple.tuple(message3.getMessageId(), "", Optional.of("my message")));
    }

    @Test
    @SuppressWarnings("unchecked")
    public void processShouldFetchHtmlMessage() throws Exception {
        MessageManager inbox = mailboxManager.getMailbox(inboxPath, session);
        ComposedMessageId message = inbox.appendMessage(
            AppendCommand.from(
                org.apache.james.mime4j.dom.Message.Builder.of()
                    .setSubject("message 1 subject")
                    .setBody("my <b>HTML</b> message", "html", StandardCharsets.UTF_8)),
            session).getId();

        GetMessagesRequest request = GetMessagesRequest.builder()
            .ids(ImmutableList.of(message.getMessageId()))
            .build();

        List<JmapResponse> result = testee.processToStream(request, methodCallId, session).collect(Collectors.toList());

        assertThat(result).hasSize(1)
            .extracting(JmapResponse::getResponse)
            .hasOnlyElementsOfType(GetMessagesResponse.class)
            .extracting(GetMessagesResponse.class::cast)
            .flatExtracting(GetMessagesResponse::list)
            .hasOnlyElementsOfType(MessageFullView.class)
            .extracting(MessageFullView.class::cast)
            .extracting(MessageFullView::getId, MessageFullView::getHtmlBody)
            .containsOnly(Tuple.tuple(message.getMessageId(), Optional.of("my <b>HTML</b> message")));
    }

    @Test
    public void processShouldReturnOnlyMandatoryPropertiesOnEmptyPropertyList() throws Exception {
        MessageManager inbox = mailboxManager.getMailbox(inboxPath, session);
        ComposedMessageId message1 = inbox.appendMessage(AppendCommand.from(this.messageContent1), session).getId();

        GetMessagesRequest request = GetMessagesRequest.builder()
            .ids(ImmutableList.of(message1.getMessageId()))
            .properties(ImmutableList.of())
            .build();

        List<JmapResponse> result = testee.processToStream(request, methodCallId, session).collect(Collectors.toList());

        assertThat(result).hasSize(1);
        assertThat(result.get(0).getProperties())
            .isEqualTo(Optional.of(ImmutableSet.of(MessageProperty.id)));
    }

    @Test
    public void processShouldReturnAllPropertiesWhenNoPropertyGiven() throws Exception {
        MessageManager inbox = mailboxManager.getMailbox(inboxPath, session);

        ComposedMessageId message1 = inbox.appendMessage(AppendCommand.from(messageContent1), session).getId();

        GetMessagesRequest request = GetMessagesRequest.builder()
            .ids(ImmutableList.of(message1.getMessageId()))
            .build();

        List<JmapResponse> result = testee.processToStream(request, methodCallId, session).collect(Collectors.toList());
        assertThat(result).hasSize(1);
        assertThat(result.get(0).getProperties())
            .isEqualTo(Optional.of(MessageProperty.allOutputProperties()));
    }

    @Test
    public void processShouldAddMandatoryPropertiesWhenNotInPropertyList() throws Exception {
        MessageManager inbox = mailboxManager.getMailbox(inboxPath, session);

        ComposedMessageId message1 = inbox.appendMessage(AppendCommand.from(messageContent1), session).getId();

        GetMessagesRequest request = GetMessagesRequest.builder()
            .ids(ImmutableList.of(message1.getMessageId()))
            .properties(ImmutableList.of(MessageProperty.subject.asFieldName()))
            .build();

        Set<MessageProperty> expected = Sets.newHashSet(MessageProperty.id, MessageProperty.subject);

        List<JmapResponse> result = testee.processToStream(request, methodCallId, session).collect(Collectors.toList());
        assertThat(result).hasSize(1);
        assertThat(result.get(0).getProperties())
            .isEqualTo(Optional.of(expected));
    }

    @Test
    public void processShouldReturnTextBodyWhenBodyInPropertyListAndEmptyHtmlBody() throws Exception {
        MessageManager inbox = mailboxManager.getMailbox(inboxPath, session);

        ComposedMessageId message1 = inbox.appendMessage(AppendCommand.from(messageContent1), session).getId();

        GetMessagesRequest request = GetMessagesRequest.builder()
            .ids(ImmutableList.of(message1.getMessageId()))
            .properties(ImmutableList.of(MessageProperty.body.asFieldName()))
            .build();

        Set<MessageProperty> expected = Sets.newHashSet(MessageProperty.id, MessageProperty.textBody);

        List<JmapResponse> result = testee.processToStream(request, methodCallId, session).collect(Collectors.toList());

        assertThat(result).hasSize(1);
        assertThat(result.get(0).getProperties())
            .isEqualTo(Optional.of(expected));
    }

    @Test
    @SuppressWarnings("unchecked")
    public void processShouldReturnTextBodyWhenEmptyTextBodyAndNotEmptyHtmlBody() throws Exception {
        MessageManager inbox = mailboxManager.getMailbox(inboxPath, session);

        ComposedMessageId message = inbox.appendMessage(
            AppendCommand.from(
                org.apache.james.mime4j.dom.Message.Builder.of()
                    .setSubject("message 1 subject")
                    .setBody("my <b>HTML</b> message", "html", StandardCharsets.UTF_8)),
            session).getId();

        GetMessagesRequest request = GetMessagesRequest.builder()
            .ids(ImmutableList.of(message.getMessageId()))
            .build();

        List<JmapResponse> result = testee.processToStream(request, methodCallId, session).collect(Collectors.toList());

        assertThat(result).hasSize(1)
            .extracting(JmapResponse::getResponse)
            .hasOnlyElementsOfType(GetMessagesResponse.class)
            .extracting(GetMessagesResponse.class::cast)
            .flatExtracting(GetMessagesResponse::list)
            .hasOnlyElementsOfType(MessageFullView.class)
            .extracting(MessageFullView.class::cast)
            .extracting(MessageFullView::getId, MessageFullView::getTextBody, MessageFullView::getHtmlBody)
            .containsOnly(Tuple.tuple(message.getMessageId(), Optional.of("my HTML message"), Optional.of("my <b>HTML</b> message")));
    }

    @Test
    @SuppressWarnings("unchecked")
    public void processShouldReturnEmptyTextBodyAndHtmlBodyWhenThoseAreEmpty() throws Exception {
        MessageManager inbox = mailboxManager.getMailbox(inboxPath, session);

        ComposedMessageId message = inbox.appendMessage(
            AppendCommand.from(org.apache.james.mime4j.dom.Message.Builder.of()
                .setSubject("message 1 subject")
                .setBody("", "html", StandardCharsets.UTF_8)),
            session).getId();

        GetMessagesRequest request = GetMessagesRequest.builder()
            .ids(ImmutableList.of(message.getMessageId()))
            .build();

        List<JmapResponse> result = testee.processToStream(request, methodCallId, session).collect(Collectors.toList());

        assertThat(result).hasSize(1)
            .extracting(JmapResponse::getResponse)
            .hasOnlyElementsOfType(GetMessagesResponse.class)
            .extracting(GetMessagesResponse.class::cast)
            .flatExtracting(GetMessagesResponse::list)
            .hasOnlyElementsOfType(MessageFullView.class)
            .extracting(MessageFullView.class::cast)
            .extracting(MessageFullView::getId, MessageFullView::getTextBody, MessageFullView::getHtmlBody)
            .containsOnly(Tuple.tuple(message.getMessageId(), Optional.empty(), Optional.of("")));
    }

    @Test
    @SuppressWarnings("unchecked")
    public void processShouldNotOverrideTextBodyWhenItIsThere() throws Exception {
        MessageManager inbox = mailboxManager.getMailbox(inboxPath, session);

        ComposedMessageId message = inbox.appendMessage(
            AppendCommand.from(org.apache.james.mime4j.dom.Message.Builder.of()
                .setSubject("message subject")
                .setBody(MultipartBuilder.create()
                    .setSubType("alternative")
                    .addBodyPart(BodyPartBuilder.create()
                        .setBody("My plain message", "plain", StandardCharsets.UTF_8))
                    .addBodyPart(BodyPartBuilder.create()
                        .setBody("<a>The </a> <strong>HTML</strong> message", "html", StandardCharsets.UTF_8))
                    .build())),
            session).getId();

        GetMessagesRequest request = GetMessagesRequest.builder()
            .ids(ImmutableList.of(message.getMessageId()))
            .build();

        List<JmapResponse> result = testee.processToStream(request, methodCallId, session).collect(Collectors.toList());

        assertThat(result).hasSize(1)
            .extracting(JmapResponse::getResponse)
            .hasOnlyElementsOfType(GetMessagesResponse.class)
            .extracting(GetMessagesResponse.class::cast)
            .flatExtracting(GetMessagesResponse::list)
            .hasOnlyElementsOfType(MessageFullView.class)
            .extracting(MessageFullView.class::cast)
            .extracting(MessageFullView::getId, MessageFullView::getTextBody, MessageFullView::getHtmlBody)
            .containsOnly(Tuple.tuple(message.getMessageId(), Optional.of("My plain message"), Optional.of("<a>The </a> <strong>HTML</strong> message")));
    }

    @Test
    public void processShouldReturnHeadersFieldWhenSpecificHeadersRequestedInPropertyList() throws Exception {
        MessageManager inbox = mailboxManager.getMailbox(inboxPath, session);

        ComposedMessageId message1 = inbox.appendMessage(
            AppendCommand.from(
                org.apache.james.mime4j.dom.Message.Builder.of()
                    .setFrom("user@domain.tld")
                    .setField(new RawField("header1", "Header1Content"))
                    .setField(new RawField("HEADer2", "Header2Content"))
                    .setSubject("message 1 subject")
                    .setBody("my message", StandardCharsets.UTF_8)),
            session).getId();

        GetMessagesRequest request = GetMessagesRequest.builder()
            .ids(ImmutableList.of(message1.getMessageId()))
            .properties(ImmutableList.of("headers.from", "headers.heADER2"))
            .build();

        Set<MessageProperty> expected = Sets.newHashSet(MessageProperty.id, MessageProperty.headers);

        List<JmapResponse> result = testee.processToStream(request, methodCallId, session).collect(Collectors.toList());

        assertThat(result).hasSize(1);
        assertThat(result.get(0).getProperties())
            .isEqualTo(Optional.of(expected));
    }

    @Test
    public void processShouldReturnPropertyFilterWhenFilteringHeadersRequested() throws Exception {
        MessageManager inbox = mailboxManager.getMailbox(inboxPath, session);

        ComposedMessageId message1 = inbox.appendMessage(
            AppendCommand.from(
                org.apache.james.mime4j.dom.Message.Builder.of()
                    .setFrom("user@domain.tld")
                    .setField(new RawField("header1", "Header1Content"))
                    .setField(new RawField("HEADer2", "Header2Content"))
                    .setSubject("message 1 subject")
                    .setBody("my message", StandardCharsets.UTF_8)),
            session).getId();

        GetMessagesRequest request = GetMessagesRequest.builder()
            .ids(ImmutableList.of(message1.getMessageId()))
            .properties(ImmutableList.of("headers.from", "headers.heADER2"))
            .build();

        List<JmapResponse> result = testee.processToStream(request, methodCallId, session).collect(Collectors.toList());

        assertThat(result)
            .hasSize(1)
            .extracting(JmapResponse::getFilterProvider)
            .are(new Condition<>(Optional::isPresent, "present"));
        SimpleFilterProvider actualFilterProvider = result.get(0).getFilterProvider().get().getRight();
        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.registerModule(new JavaTimeModule());
        objectMapper.setFilterProvider(actualFilterProvider.setDefaultFilter(SimpleBeanPropertyFilter.serializeAll()));
        String response = objectMapper.writer().writeValueAsString(result.get(0));
        assertThat(JsonPath.parse(response).<Map<String, String>>read("$.response.list[0].headers")).containsOnly(MapEntry.entry("From", "user@domain.tld"), MapEntry.entry("HEADer2", "Header2Content"));
    }

    @Test
    public void processShouldReturnOneMessageWhenMessageInSeveralMailboxes() throws Exception {
        MessageManager inbox = mailboxManager.getMailbox(inboxPath, session);

        ComposedMessageId message1 = inbox.appendMessage(
            AppendCommand.from(
                org.apache.james.mime4j.dom.Message.Builder.of()
                    .setFrom("user@domain.tld")
                    .setField(new RawField("header1", "Header1Content"))
                    .setField(new RawField("HEADer2", "Header2Content"))
                    .setSubject("message 1 subject")
                    .setBody("my message", StandardCharsets.UTF_8)),
            session).getId();

        MailboxId customMailboxId = mailboxManager.getMailbox(customMailboxPath, session).getId();
        messageIdManager.setInMailboxes(message1.getMessageId(),
            ImmutableList.of(message1.getMailboxId(), customMailboxId),
            session);

        GetMessagesRequest request = GetMessagesRequest.builder()
            .ids(ImmutableList.of(message1.getMessageId()))
            .properties(ImmutableList.of("mailboxIds"))
            .build();

        List<JmapResponse> result = testee.processToStream(request, methodCallId, session).collect(Collectors.toList());

        assertThat(result).hasSize(1);
        Method.Response response = result.get(0).getResponse();
        assertThat(response).isInstanceOf(GetMessagesResponse.class);
        GetMessagesResponse getMessagesResponse = (GetMessagesResponse) response;
        assertThat(getMessagesResponse.list()).hasSize(1)
            .hasOnlyElementsOfType(MessageMetadataView.class)
            .extracting(MessageMetadataView.class::cast)
            .flatExtracting(MessageMetadataView::getMailboxIds)
            .containsOnly(customMailboxId, message1.getMailboxId());
    }

    @Test
    public void processShouldReturnMetadataWhenOnlyMailboxIds() throws Exception {
        MessageManager inbox = mailboxManager.getMailbox(inboxPath, session);

        ComposedMessageId message1 = inbox.appendMessage(
            AppendCommand.from(
                org.apache.james.mime4j.dom.Message.Builder.of()
                    .setFrom("user@domain.tld")
                    .setField(new RawField("header1", "Header1Content"))
                    .setField(new RawField("HEADer2", "Header2Content"))
                    .setSubject("message 1 subject")
                    .setBody("my message", StandardCharsets.UTF_8)),
            session).getId();

        MailboxId customMailboxId = mailboxManager.getMailbox(customMailboxPath, session).getId();
        messageIdManager.setInMailboxes(message1.getMessageId(),
            ImmutableList.of(message1.getMailboxId(), customMailboxId),
            session);

        GetMessagesRequest request = GetMessagesRequest.builder()
            .ids(ImmutableList.of(message1.getMessageId()))
            .properties(ImmutableList.of("mailboxIds"))
            .build();

        List<JmapResponse> result = testee.processToStream(request, methodCallId, session).collect(Collectors.toList());

        assertThat(result).hasSize(1);
        Method.Response response = result.get(0).getResponse();
        assertThat(response).isInstanceOf(GetMessagesResponse.class);
        GetMessagesResponse getMessagesResponse = (GetMessagesResponse) response;
        assertThat(getMessagesResponse.list())
            .hasSize(1)
            .hasOnlyElementsOfType(MessageMetadataView.class);
    }

    @Test
    public void processShouldReturnFullViewWhenRequestedTextBody() throws Exception {
        MessageManager inbox = mailboxManager.getMailbox(inboxPath, session);

        ComposedMessageId message1 = inbox.appendMessage(
            AppendCommand.from(
                org.apache.james.mime4j.dom.Message.Builder.of()
                    .setFrom("user@domain.tld")
                    .setField(new RawField("header1", "Header1Content"))
                    .setField(new RawField("HEADer2", "Header2Content"))
                    .setSubject("message 1 subject")
                    .setBody("my message", StandardCharsets.UTF_8)),
            session).getId();

        MailboxId customMailboxId = mailboxManager.getMailbox(customMailboxPath, session).getId();
        messageIdManager.setInMailboxes(message1.getMessageId(),
            ImmutableList.of(message1.getMailboxId(), customMailboxId),
            session);

        GetMessagesRequest request = GetMessagesRequest.builder()
            .ids(ImmutableList.of(message1.getMessageId()))
            .properties(ImmutableList.of("mailboxIds", "textBody"))
            .build();

        List<JmapResponse> result = testee.processToStream(request, methodCallId, session).collect(Collectors.toList());

        assertThat(result).hasSize(1);
        Method.Response response = result.get(0).getResponse();
        assertThat(response).isInstanceOf(GetMessagesResponse.class);
        GetMessagesResponse getMessagesResponse = (GetMessagesResponse) response;
        assertThat(getMessagesResponse.list())
            .hasSize(1)
            .hasOnlyElementsOfType(MessageFullView.class);
    }

    @Test
    public void processShouldReturnHeaderViewWhenRequestedTo() throws Exception {
        MessageManager inbox = mailboxManager.getMailbox(inboxPath, session);

        ComposedMessageId message1 = inbox.appendMessage(
            AppendCommand.from(
                org.apache.james.mime4j.dom.Message.Builder.of()
                    .setFrom("user@domain.tld")
                    .setField(new RawField("header1", "Header1Content"))
                    .setField(new RawField("HEADer2", "Header2Content"))
                    .setSubject("message 1 subject")
                    .setBody("my message", StandardCharsets.UTF_8)),
            session).getId();

        MailboxId customMailboxId = mailboxManager.getMailbox(customMailboxPath, session).getId();
        messageIdManager.setInMailboxes(message1.getMessageId(),
            ImmutableList.of(message1.getMailboxId(), customMailboxId),
            session);

        GetMessagesRequest request = GetMessagesRequest.builder()
            .ids(ImmutableList.of(message1.getMessageId()))
            .properties(ImmutableList.of("mailboxIds", "to"))
            .build();

        List<JmapResponse> result = testee.processToStream(request, methodCallId, session).collect(Collectors.toList());

        assertThat(result).hasSize(1);
        Method.Response response = result.get(0).getResponse();
        assertThat(response).isInstanceOf(GetMessagesResponse.class);
        GetMessagesResponse getMessagesResponse = (GetMessagesResponse) response;
        assertThat(getMessagesResponse.list())
            .hasSize(1)
            .hasOnlyElementsOfType(MessageHeaderView.class);
    }

    @Test
    public void processShouldNotFailOnSingleMessageFailure() throws Exception {
        MessageManager inbox = mailboxManager.getMailbox(inboxPath, session);

        org.apache.james.mime4j.dom.Message messageContent = org.apache.james.mime4j.dom.Message.Builder.of()
            .setFrom("user@domain.tld")
            .setField(new RawField("header1", "Header1Content"))
            .setField(new RawField("HEADer2", "Header2Content"))
            .setSubject("message 1 subject")
            .setBody("my message", StandardCharsets.UTF_8)
            .build();

        ComposedMessageId message1 = inbox.appendMessage(AppendCommand.from(messageContent), session).getId();
        ComposedMessageId message2 = inbox.appendMessage(AppendCommand.from(messageContent), session).getId();

        doCallRealMethod()
            .doReturn(Mono.error(new RuntimeException()))
            .when(messageMetadataViewFactory)
            .fromMessageResults(any());

        GetMessagesRequest request = GetMessagesRequest.builder()
            .ids(ImmutableList.of(message1.getMessageId(), message2.getMessageId()))
            .properties(ImmutableList.of("mailboxIds"))
            .build();

        List<JmapResponse> responses = testee.processToStream(request, methodCallId, session).collect(ImmutableList.toImmutableList());

        assertThat(responses).hasSize(1);
        Method.Response response = responses.get(0).getResponse();
        assertThat(response).isInstanceOf(GetMessagesResponse.class);
        GetMessagesResponse getMessagesResponse = (GetMessagesResponse) response;
        assertThat(getMessagesResponse.list()).hasSize(1);
    }

    @Test
    public void processShouldReturnKeywordsForMessageFlags() throws Exception {
        Flags flags = FlagsBuilder.builder()
            .add(Flag.ANSWERED, Flag.DRAFT)
            .build();
        MessageManager inbox = mailboxManager.getMailbox(inboxPath, session);
        ComposedMessageId message1 = inbox.appendMessage(
            AppendCommand.builder()
                .withFlags(flags)
                .build(messageContent1),
            session).getId();
        ComposedMessageId message2 = inbox.appendMessage(
            AppendCommand.builder()
                .withFlags(flags)
                .build(messageContent2),
            session).getId();
        ComposedMessageId message3 = inbox.appendMessage(
            AppendCommand.builder()
                .withFlags(flags)
                .build(messageContent3),
            session).getId();

        GetMessagesRequest request = GetMessagesRequest.builder()
            .ids(ImmutableList.of(message1.getMessageId(),
                message2.getMessageId(),
                message3.getMessageId()))
            .build();

        List<JmapResponse> result = testee.processToStream(request, methodCallId, session).collect(Collectors.toList());

        assertThat(result).hasSize(1)
            .extracting(JmapResponse::getResponse)
            .hasOnlyElementsOfType(GetMessagesResponse.class)
            .extracting(GetMessagesResponse.class::cast)
            .flatExtracting(GetMessagesResponse::list)
            .hasOnlyElementsOfType(MessageFullView.class)
            .extracting(MessageFullView.class::cast)
            .extracting(MessageFullView::getKeywords)
            .containsOnly( ImmutableMap.of(
                    "$Answered", true,
                    "$Draft", true),
                ImmutableMap.of(
                    "$Answered", true,
                    "$Draft", true),
                ImmutableMap.of(
                    "$Answered", true,
                    "$Draft", true));

    }


    @Test
    public void processShouldReturnKeywordsWithoutUnsupportedKeywordsForMessageFlags() throws Exception {
        Flags flags1 = FlagsBuilder.builder()
            .add(Flag.ANSWERED, Flag.DRAFT, Flag.DELETED)
            .build();
        Flags flags2 = FlagsBuilder.builder()
            .add(Flag.ANSWERED, Flag.DRAFT)
            .build();
        Flags flags3 = FlagsBuilder.builder()
            .add(Flag.ANSWERED, Flag.DRAFT, Flag.RECENT)
            .build();
        MessageManager inbox = mailboxManager.getMailbox(inboxPath, session);
        ComposedMessageId message1 = inbox.appendMessage(
            AppendCommand.builder()
                .withFlags(flags1)
                .build(messageContent1),
            session).getId();
        ComposedMessageId message2 = inbox.appendMessage(
            AppendCommand.builder()
                .withFlags(flags2)
                .build(messageContent2),
            session).getId();
        ComposedMessageId message3 = inbox.appendMessage(
            AppendCommand.builder()
                .withFlags(flags3)
                .build(messageContent3),
            session).getId();

        GetMessagesRequest request = GetMessagesRequest.builder()
            .ids(ImmutableList.of(message1.getMessageId(),
                message2.getMessageId(),
                message3.getMessageId()))
            .build();

        List<JmapResponse> result = testee.processToStream(request, methodCallId, session).collect(Collectors.toList());

        assertThat(result).hasSize(1)
            .extracting(JmapResponse::getResponse)
            .hasOnlyElementsOfType(GetMessagesResponse.class)
            .extracting(GetMessagesResponse.class::cast)
            .flatExtracting(GetMessagesResponse::list)
            .hasOnlyElementsOfType(MessageFullView.class)
            .extracting(MessageFullView.class::cast)
            .extracting(MessageFullView::getKeywords)
            .containsOnly(ImmutableMap.of(
                    "$Answered", true,
                    "$Draft", true),
                ImmutableMap.of(
                    "$Answered", true,
                    "$Draft", true),
                ImmutableMap.of(
                    "$Answered", true,
                    "$Draft", true));

    }

    @Test
    public void processShouldReturnKeywordsWithoutForwardedWhenForwardedUserFlagsMessages() throws Exception {
        Flags flags = FlagsBuilder.builder()
            .add(Flag.ANSWERED, Flag.DELETED)
            .add(FORWARDED)
            .build();
        MessageManager inbox = mailboxManager.getMailbox(inboxPath, session);

        ComposedMessageId message1 = inbox.appendMessage(
            AppendCommand.builder()
                .withFlags(flags)
                .build(messageContent1),
            session).getId();

        GetMessagesRequest request = GetMessagesRequest.builder()
            .ids(ImmutableList.of(message1.getMessageId()))
            .build();

        List<JmapResponse> result = testee.processToStream(request, methodCallId, session).collect(Collectors.toList());

        assertThat(result).hasSize(1)
            .extracting(JmapResponse::getResponse)
            .hasOnlyElementsOfType(GetMessagesResponse.class)
            .extracting(GetMessagesResponse.class::cast)
            .flatExtracting(GetMessagesResponse::list)
            .hasOnlyElementsOfType(MessageFullView.class)
            .extracting(MessageFullView.class::cast)
            .extracting(MessageFullView::getKeywords)
            .containsOnly(ImmutableMap.of(
                "$Answered", true,
                FORWARDED, true));
    }

}
