package io.qameta.allure.retry;

import io.qameta.allure.Aggregator;
import io.qameta.allure.core.Configuration;
import io.qameta.allure.core.LaunchResults;
import io.qameta.allure.entity.TestResult;
import io.qameta.allure.entity.Time;

import java.io.IOException;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * The plugin that process test retries.
 *
 * @since 2.0
 */
public class RetryPlugin implements Aggregator {

    public static final String RETRY_BLOCK_NAME = "retries";

    @SuppressWarnings({"PMD.AvoidLiteralsInIfCondition", "PMD.AvoidInstantiatingObjectsInLoops"})
    @Override
    public void aggregate(final Configuration configuration,
                          final List<LaunchResults> launchesResults,
                          final Path outputDirectory) throws IOException {

        Map<String, List<TestResult>> byHistory = launchesResults.stream()
                .flatMap(results -> results.getAllResults().stream())
                .filter(result -> Objects.nonNull(result.getHistoryId()))
                .collect(Collectors.toMap(TestResult::getHistoryId, Arrays::asList, this::merge));
        byHistory.forEach((historyId, results) -> {
            final List<TestResult> sorted = results.stream()
                    .sorted(byTime())
                    .collect(Collectors.toList());
            if (sorted.size() > 1) {
                final TestResult first = sorted.remove(0);
                final List<RetryItem> retries = new ArrayList<>();
                first.addExtraBlock(RETRY_BLOCK_NAME, retries);
                for (TestResult result : sorted) {
                    result.setHidden(true);
                    retries.add(new RetryItem()
                            .withUid(result.getUid())
                            .withStatus(result.getStatus())
                            .withTime(result.getTime())
                    );
                }
            }
        });
    }

    private List<TestResult> merge(final List<TestResult> first,
                                   final List<TestResult> second) {
        final List<TestResult> merged = new ArrayList<>();
        merged.addAll(first);
        merged.addAll(second);
        return merged;
    }

    private Comparator<TestResult> byTime() {
        return Comparator.comparing(
                TestResult::getTime,
                Comparator.comparing(Time::getStart)
        ).reversed();
    }
}

@@ -476,16 +476,159 @@
 ctors;%0A%0A
+import static java.util.Comparator.comparing;%0Aimport static java.util.Comparator.naturalOrder;%0Aimport static java.util.Comparator.nullsFirst;%0A%0A
 /**%0A * T
@@ -2593,27 +2593,16 @@
  return 
-Comparator.
 comparin
@@ -2657,27 +2657,27 @@
         
-Comparator.
+nullsFirst(
 comparin
@@ -2692,16 +2692,45 @@
 getStart
+, nullsFirst(naturalOrder()))
 )%0A      

fix npe in retry plugin