/****************************************************************
 * 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.webadmin.integration.rabbitmq;

import static io.restassured.RestAssured.given;
import static io.restassured.RestAssured.when;
import static io.restassured.RestAssured.with;
import static org.awaitility.Duration.ONE_HUNDRED_MILLISECONDS;
import static org.awaitility.Duration.ONE_MINUTE;
import static org.awaitility.Duration.TEN_SECONDS;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.Matchers.containsInAnyOrder;
import static org.hamcrest.Matchers.hasSize;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

import org.apache.james.CassandraExtension;
import org.apache.james.CassandraRabbitMQJamesServerMain;
import org.apache.james.DockerElasticSearchExtension;
import org.apache.james.GuiceJamesServer;
import org.apache.james.GuiceModuleTestExtension;
import org.apache.james.JamesServerBuilder;
import org.apache.james.JamesServerExtension;
import org.apache.james.core.Username;
import org.apache.james.junit.categories.BasicFeature;
import org.apache.james.mailbox.DefaultMailboxes;
import org.apache.james.mailbox.events.Event;
import org.apache.james.mailbox.events.Group;
import org.apache.james.mailbox.events.MailboxListener;
import org.apache.james.mailbox.model.MailboxId;
import org.apache.james.mailbox.model.MailboxPath;
import org.apache.james.modules.AwsS3BlobStoreExtension;
import org.apache.james.modules.MailboxProbeImpl;
import org.apache.james.modules.RabbitMQExtension;
import org.apache.james.probe.DataProbe;
import org.apache.james.utils.DataProbeImpl;
import org.apache.james.utils.WebAdminGuiceProbe;
import org.apache.james.webadmin.WebAdminUtils;
import org.apache.james.webadmin.integration.WebadminIntegrationTestModule;
import org.apache.james.webadmin.routes.EventDeadLettersRoutes;
import org.apache.james.webadmin.routes.TasksRoutes;
import org.awaitility.Awaitility;
import org.awaitility.Duration;
import org.awaitility.core.ConditionFactory;
import org.eclipse.jetty.http.HttpStatus;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Tag;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtensionContext;
import org.junit.jupiter.api.extension.ParameterContext;
import org.junit.jupiter.api.extension.ParameterResolutionException;
import org.junit.jupiter.api.extension.RegisterExtension;

import com.google.inject.Module;
import com.google.inject.multibindings.Multibinder;

import io.restassured.RestAssured;
import io.restassured.http.ContentType;

@Tag(BasicFeature.TAG)
class RabbitMQEventDeadLettersIntegrationTest {
    public static class RetryEventsListenerGroup extends Group {

    }

    public static class RetryEventsListener implements MailboxListener.GroupMailboxListener {
        static final Group GROUP = new RetryEventsListenerGroup();

        private final AtomicInteger totalCalls;
        private int callsBeforeSuccess;
        private Map<Event.EventId, Integer> callsByEventId;
        private List<Event> successfulEvents;

        RetryEventsListener() {
            this.callsBeforeSuccess = 0;
            this.callsByEventId = new HashMap<>();
            this.successfulEvents = new ArrayList<>();
            this.totalCalls = new AtomicInteger(0);
        }

        @Override
        public Group getDefaultGroup() {
            return GROUP;
        }

        @Override
        public void event(Event event) throws Exception {
            totalCalls.incrementAndGet();
            if (done(event)) {
                callsByEventId.remove(event.getEventId());
                successfulEvents.add(event);
            } else {
                increaseRetriesCount(event);
                throw new RuntimeException("throw to trigger retry");
            }
        }

        private void increaseRetriesCount(Event event) {
            callsByEventId.put(event.getEventId(), retriesCount(event) + 1);
        }

        int retriesCount(Event event) {
            return callsByEventId.getOrDefault(event.getEventId(), 0);
        }

        boolean done(Event event) {
            return retriesCount(event) >= callsBeforeSuccess;
        }

        List<Event> getSuccessfulEvents() {
            return successfulEvents;
        }

        void callsPerEventBeforeSuccess(int retriesBeforeSuccess) {
            this.callsBeforeSuccess = retriesBeforeSuccess;
        }
    }

    public static class RetryEventsListenerExtension implements GuiceModuleTestExtension {
        private RetryEventsListener retryEventsListener;

        @Override
        public void beforeEach(ExtensionContext extensionContext) throws Exception {
            retryEventsListener = new RetryEventsListener();
        }

        @Override
        public Module getModule() {
            return binder -> Multibinder.newSetBinder(binder, MailboxListener.GroupMailboxListener.class)
                .addBinding()
                .toInstance(retryEventsListener);
        }

        @Override
        public boolean supportsParameter(ParameterContext parameterContext, ExtensionContext extensionContext) throws ParameterResolutionException {
            return parameterContext.getParameter().getType() == RetryEventsListener.class;
        }

        @Override
        public Object resolveParameter(ParameterContext parameterContext, ExtensionContext extensionContext) throws ParameterResolutionException {
            return retryEventsListener;
        }
    }
    
    @RegisterExtension
    static JamesServerExtension testExtension = new JamesServerBuilder()
        .extension(new DockerElasticSearchExtension())
        .extension(new CassandraExtension())
        .extension(new AwsS3BlobStoreExtension())
        .extension(new RabbitMQExtension())
        .extension(new RetryEventsListenerExtension())
        .server(configuration -> GuiceJamesServer.forConfiguration(configuration)
            .combineWith(CassandraRabbitMQJamesServerMain.MODULES)
            .overrideWith(new WebadminIntegrationTestModule()))
        .build();

    //This value is duplicated from default configuration to ensure we keep the same behavior over time
    //unless we really want to change that default value
    private static final int MAX_RETRIES = 3;

    private static final String DOMAIN = "domain.tld";
    private static final String BOB = "bob@" + DOMAIN;
    private static final String BOB_PASSWORD = "bobPassword";
    private static final String EVENTS_ACTION = "reDeliver";
    private static final String GROUP_ID = new RetryEventsListenerGroup().asString();
    private static final MailboxPath BOB_INBOX_PATH = MailboxPath.inbox(Username.of(BOB));

    private Duration slowPacedPollInterval = ONE_HUNDRED_MILLISECONDS;
    private ConditionFactory calmlyAwait = Awaitility.with()
        .pollInterval(slowPacedPollInterval)
        .and()
        .with()
        .pollDelay(slowPacedPollInterval)
        .await();
    private ConditionFactory awaitAtMostTenSeconds = calmlyAwait.atMost(10, TimeUnit.SECONDS);
    private MailboxProbeImpl mailboxProbe;

    @BeforeEach
    void setUp(GuiceJamesServer guiceJamesServer) throws Exception {
        DataProbe dataProbe = guiceJamesServer.getProbe(DataProbeImpl.class);
        mailboxProbe = guiceJamesServer.getProbe(MailboxProbeImpl.class);
        WebAdminGuiceProbe webAdminGuiceProbe = guiceJamesServer.getProbe(WebAdminGuiceProbe.class);

        RestAssured.requestSpecification = WebAdminUtils.buildRequestSpecification(webAdminGuiceProbe.getWebAdminPort())
            .build();

        dataProbe.addDomain(DOMAIN);
        dataProbe.addUser(BOB, BOB_PASSWORD);
    }

    private MailboxId generateInitialEvent() {
        return mailboxProbe.createMailbox(BOB_INBOX_PATH);
    }

    private void generateSecondEvent() {
        mailboxProbe.createMailbox(MailboxPath.forUser(Username.of(BOB), DefaultMailboxes.OUTBOX));
    }

    private String retrieveFirstFailedInsertionId() {
        calmlyAwait.atMost(TEN_SECONDS)
            .untilAsserted(() ->
                when()
                    .get(EventDeadLettersRoutes.BASE_PATH + "/groups/" + GROUP_ID)
                .then()
                    .body(".", hasSize(1)));

        return (String) with()
            .get(EventDeadLettersRoutes.BASE_PATH + "/groups/" + GROUP_ID)
            .jsonPath()
            .getList(".")
            .get(0);
    }

    @Test
    void failedEventShouldBeStoredInDeadLetterUnderItsGroupId(RetryEventsListener retryEventsListener) {
        retryEventsListener.callsPerEventBeforeSuccess(MAX_RETRIES + 1);
        generateInitialEvent();

        waitForCalls(retryEventsListener, MAX_RETRIES + 1);

        when()
            .get(EventDeadLettersRoutes.BASE_PATH + "/groups/" + GROUP_ID)
        .then()
            .statusCode(HttpStatus.OK_200)
            .contentType(ContentType.JSON)
            .body(".", hasSize(1));
    }

    @Test
    void successfulEventShouldNotBeStoredInDeadLetter(RetryEventsListener retryEventsListener) {
        retryEventsListener.callsPerEventBeforeSuccess(MAX_RETRIES - 1);
        generateInitialEvent();

        calmlyAwait.atMost(ONE_MINUTE).until(() -> !retryEventsListener.successfulEvents.isEmpty());

        when()
            .get(EventDeadLettersRoutes.BASE_PATH + "/groups")
        .then()
            .statusCode(HttpStatus.OK_200)
            .contentType(ContentType.JSON)
            .body(".", hasSize(0));
    }

    @Test
    void groupIdOfFailedEventShouldBeStoredInDeadLetter(RetryEventsListener retryEventsListener) {
        retryEventsListener.callsPerEventBeforeSuccess(MAX_RETRIES + 1);
        generateInitialEvent();

        waitForCalls(retryEventsListener, MAX_RETRIES + 1);

        when()
            .get(EventDeadLettersRoutes.BASE_PATH + "/groups")
        .then()
            .statusCode(HttpStatus.OK_200)
            .contentType(ContentType.JSON)
            .body(".", containsInAnyOrder(GROUP_ID));
    }

    @Test
    void failedEventShouldBeStoredInDeadLetter(RetryEventsListener retryEventsListener) {
        retryEventsListener.callsPerEventBeforeSuccess(MAX_RETRIES + 1);
        MailboxId mailboxId = generateInitialEvent();

        waitForCalls(retryEventsListener, MAX_RETRIES + 1);

        String failedInsertionId = retrieveFirstFailedInsertionId();

        when()
            .get(EventDeadLettersRoutes.BASE_PATH + "/groups/" + GROUP_ID + "/" + failedInsertionId)
        .then()
            .statusCode(HttpStatus.OK_200)
            .contentType(ContentType.JSON)
            .body("MailboxAdded.mailboxId", is(mailboxId.serialize()))
            .body("MailboxAdded.user", is(BOB))
            .body("MailboxAdded.mailboxPath.namespace", is(BOB_INBOX_PATH.getNamespace()))
            .body("MailboxAdded.mailboxPath.user", is(BOB_INBOX_PATH.getUser().asString()))
            .body("MailboxAdded.mailboxPath.name", is(BOB_INBOX_PATH.getName()));
    }

    @Test
    void multipleFailedEventShouldBeStoredInDeadLetter(RetryEventsListener retryEventsListener) {
        retryEventsListener.callsPerEventBeforeSuccess(MAX_RETRIES + 1);
        generateInitialEvent();
        generateSecondEvent();

        waitForCalls(retryEventsListener, (MAX_RETRIES + 1) * 2);

        when()
            .get(EventDeadLettersRoutes.BASE_PATH + "/groups/" + GROUP_ID)
        .then()
            .statusCode(HttpStatus.OK_200)
            .contentType(ContentType.JSON)
            .body(".", hasSize(2));
    }

    @Test
    void failedEventShouldNotBeInDeadLetterAfterBeingDeleted(RetryEventsListener retryEventsListener) {
        retryEventsListener.callsPerEventBeforeSuccess(MAX_RETRIES + 1);
        generateInitialEvent();

        waitForCalls(retryEventsListener, MAX_RETRIES + 1);

        String failedInsertionId = retrieveFirstFailedInsertionId();

        with()
            .delete(EventDeadLettersRoutes.BASE_PATH + "/groups/" + GROUP_ID + "/" + failedInsertionId);

        when()
            .get(EventDeadLettersRoutes.BASE_PATH + "/groups/" + GROUP_ID + "/" + failedInsertionId)
        .then()
            .statusCode(HttpStatus.NOT_FOUND_404);
    }

    @Test
    void taskShouldBeCompletedAfterSuccessfulRedelivery(RetryEventsListener retryEventsListener) {
        retryEventsListener.callsPerEventBeforeSuccess(MAX_RETRIES + 1);
        generateInitialEvent();

        waitForCalls(retryEventsListener, MAX_RETRIES + 1);

        String failedInsertionId = retrieveFirstFailedInsertionId();

        String taskId = with()
            .queryParam("action", EVENTS_ACTION)
        .post(EventDeadLettersRoutes.BASE_PATH + "/groups/" + GROUP_ID + "/" + failedInsertionId)
            .jsonPath()
            .get("taskId");

        given()
            .basePath(TasksRoutes.BASE)
        .when()
            .get(taskId + "/await")
        .then()
            .body("status", is("completed"))
            .body("additionalInformation.successfulRedeliveriesCount", is(1))
            .body("additionalInformation.failedRedeliveriesCount", is(0))
            .body("additionalInformation.group", is(GROUP_ID))
            .body("additionalInformation.insertionId", is(failedInsertionId));
    }

    @Test
    void failedEventShouldNotBeInDeadLettersAfterSuccessfulRedelivery(RetryEventsListener retryEventsListener) {
        retryEventsListener.callsPerEventBeforeSuccess(MAX_RETRIES + 1);
        generateInitialEvent();

        waitForCalls(retryEventsListener, MAX_RETRIES + 1);

        String failedInsertionId = retrieveFirstFailedInsertionId();

        String taskId = with()
            .queryParam("action", EVENTS_ACTION)
        .post(EventDeadLettersRoutes.BASE_PATH + "/groups/" + GROUP_ID + "/" + failedInsertionId)
            .jsonPath()
            .get("taskId");

        with()
            .basePath(TasksRoutes.BASE)
            .get(taskId + "/await");

        when()
            .get("/events/deadLetter/groups/" + GROUP_ID + "/" + failedInsertionId)
        .then()
            .statusCode(HttpStatus.NOT_FOUND_404);
    }

    @Test
    void failedEventShouldBeCorrectlyProcessedByListenerAfterSuccessfulRedelivery(RetryEventsListener retryEventsListener) throws InterruptedException {
        retryEventsListener.callsPerEventBeforeSuccess(MAX_RETRIES + 1);
        generateInitialEvent();

        waitForCalls(retryEventsListener, MAX_RETRIES + 1);

        String failedInsertionId = retrieveFirstFailedInsertionId();

        String taskId = with()
            .queryParam("action", EVENTS_ACTION)
        .post(EventDeadLettersRoutes.BASE_PATH + "/groups/" + GROUP_ID + "/" + failedInsertionId)
            .jsonPath()
            .get("taskId");

        with()
            .basePath(TasksRoutes.BASE)
            .get(taskId + "/await");

        awaitAtMostTenSeconds.until(() -> retryEventsListener.getSuccessfulEvents().size() == 1);
    }

    private void waitForCalls(RetryEventsListener retryEventsListener, int count) {
        calmlyAwait.atMost(ONE_MINUTE).until(() -> retryEventsListener.totalCalls.intValue() >= count);
    }

    @Test
    void taskShouldBeCompletedAfterSuccessfulGroupRedelivery(RetryEventsListener retryEventsListener) {
        retryEventsListener.callsPerEventBeforeSuccess(MAX_RETRIES + 1);
        generateInitialEvent();
        generateSecondEvent();

        waitForCalls(retryEventsListener, (MAX_RETRIES + 1) * 2);

        String taskId = with()
            .queryParam("action", EVENTS_ACTION)
        .post(EventDeadLettersRoutes.BASE_PATH + "/groups/" + GROUP_ID)
            .jsonPath()
            .get("taskId");

        given()
            .basePath(TasksRoutes.BASE)
        .when()
            .get(taskId + "/await")
        .then()
            .body("status", is("completed"))
            .body("additionalInformation.successfulRedeliveriesCount", is(2))
            .body("additionalInformation.failedRedeliveriesCount", is(0))
            .body("additionalInformation.group", is(GROUP_ID));
    }

    @Test
    void multipleFailedEventsShouldNotBeInDeadLettersAfterSuccessfulGroupRedelivery(RetryEventsListener retryEventsListener) {
        retryEventsListener.callsPerEventBeforeSuccess(MAX_RETRIES + 1);
        generateInitialEvent();
        generateSecondEvent();

        waitForCalls(retryEventsListener, (MAX_RETRIES + 1) * 2);

        String taskId = with()
            .queryParam("action", EVENTS_ACTION)
        .post(EventDeadLettersRoutes.BASE_PATH + "/groups/" + GROUP_ID)
            .jsonPath()
            .get("taskId");

        with()
            .basePath(TasksRoutes.BASE)
            .get(taskId + "/await");

        when()
            .get(EventDeadLettersRoutes.BASE_PATH + "/groups/" + GROUP_ID)
        .then()
            .statusCode(HttpStatus.OK_200)
            .contentType(ContentType.JSON)
            .body(".", hasSize(0));
    }

    @Test
    void multipleFailedEventsShouldBeCorrectlyProcessedByListenerAfterSuccessfulGroupRedelivery(RetryEventsListener retryEventsListener) {
        retryEventsListener.callsPerEventBeforeSuccess(MAX_RETRIES + 1);
        generateInitialEvent();
        generateSecondEvent();

        waitForCalls(retryEventsListener, (MAX_RETRIES + 1) * 2);

        String taskId = with()
            .queryParam("action", EVENTS_ACTION)
        .post(EventDeadLettersRoutes.BASE_PATH + "/groups/" + GROUP_ID)
            .jsonPath()
            .get("taskId");

        with()
            .basePath(TasksRoutes.BASE)
            .get(taskId + "/await");

        awaitAtMostTenSeconds.until(() -> retryEventsListener.getSuccessfulEvents().size() == 2);
    }

    @Test
    void taskShouldBeCompletedAfterSuccessfulAllRedelivery(RetryEventsListener retryEventsListener) {
        retryEventsListener.callsPerEventBeforeSuccess(MAX_RETRIES + 1);
        generateInitialEvent();
        generateSecondEvent();

        waitForCalls(retryEventsListener, (MAX_RETRIES + 1) * 2);

        String taskId = with()
            .queryParam("action", EVENTS_ACTION)
        .post(EventDeadLettersRoutes.BASE_PATH)
            .jsonPath()
            .get("taskId");

        given()
            .basePath(TasksRoutes.BASE)
        .when()
            .get(taskId + "/await")
        .then()
            .body("status", is("completed"))
            .body("additionalInformation.successfulRedeliveriesCount", is(2))
            .body("additionalInformation.failedRedeliveriesCount", is(0));
    }

    @Test
    void multipleFailedEventsShouldNotBeInDeadLettersAfterSuccessfulAllRedelivery(RetryEventsListener retryEventsListener) {
        retryEventsListener.callsPerEventBeforeSuccess(MAX_RETRIES + 1);
        generateInitialEvent();
        generateSecondEvent();

        waitForCalls(retryEventsListener, (MAX_RETRIES + 1) * 2);

        String taskId = with()
            .queryParam("action", EVENTS_ACTION)
        .post(EventDeadLettersRoutes.BASE_PATH)
            .jsonPath()
            .get("taskId");

        with()
            .basePath(TasksRoutes.BASE)
            .get(taskId + "/await");

        when()
            .get(EventDeadLettersRoutes.BASE_PATH + "/groups/" + GROUP_ID)
        .then()
            .statusCode(HttpStatus.OK_200)
            .contentType(ContentType.JSON)
            .body(".", hasSize(0));
    }

    @Test
    void multipleFailedEventsShouldBeCorrectlyProcessedByListenerAfterSuccessfulAllRedelivery(RetryEventsListener retryEventsListener) {
        retryEventsListener.callsPerEventBeforeSuccess(MAX_RETRIES + 1);
        generateInitialEvent();
        generateSecondEvent();

        waitForCalls(retryEventsListener, (MAX_RETRIES + 1) * 2);

        String taskId = with()
            .queryParam("action", EVENTS_ACTION)
        .post(EventDeadLettersRoutes.BASE_PATH)
            .jsonPath()
            .get("taskId");

        with()
            .basePath(TasksRoutes.BASE)
            .get(taskId + "/await");

        awaitAtMostTenSeconds.until(() -> retryEventsListener.getSuccessfulEvents().size() == 2);
    }

    @Disabled("retry rest API delivers only once, see JAMES-2907. We need same retry cound for this test to work")
    @Test
    void failedEventShouldStillBeInDeadLettersAfterFailedRedelivery(RetryEventsListener retryEventsListener) {
        retryEventsListener.callsPerEventBeforeSuccess(MAX_RETRIES * 2 + 1);
        generateInitialEvent();

        waitForCalls(retryEventsListener, MAX_RETRIES + 1);

        String failedInsertionId = retrieveFirstFailedInsertionId();

        String taskId = with()
            .queryParam("action", EVENTS_ACTION)
        .post(EventDeadLettersRoutes.BASE_PATH + "/groups/" + GROUP_ID + "/" + failedInsertionId)
            .jsonPath()
            .get("taskId");

        with()
            .basePath(TasksRoutes.BASE)
            .get(taskId + "/await");

        String newFailedInsertionId = retrieveFirstFailedInsertionId();

        when()
            .get(EventDeadLettersRoutes.BASE_PATH + "/groups/" + GROUP_ID + "/" + newFailedInsertionId)
        .then()
            .statusCode(HttpStatus.OK_200);
    }
}
