class ReportCreator {

  public ResponseReport buildResponseReport(
      final ComponentsVulnerability report,
      final PackageLock packageLock)
  {
    List<Action> actions = new ArrayList<>();
    Map<String, Advisory> advisories = new HashMap<>();
    List<Object> muted = new ArrayList<>();

    int index = 1;
    for (Entry<AuditComponent, List<Vulnerability>> entry : report.getAuditComponents().entrySet()) {
      AuditComponent component = entry.getKey();
      List<Vulnerability> vulnerabilities = entry.getValue();
      // from the critical issues to the lowest ones
      vulnerabilities.sort(Comparator.comparing(Vulnerability::getSeverity,
          Comparator.comparingInt(v -> v.getSeverityRange().getMinimum())).reversed());
      for (Vulnerability vulnerability : vulnerabilities) {
        List<Resolve> resolvesForOneComponent =
            packageLock.createResolve(index, component.getName(), component.getVersion());
        if (resolvesForOneComponent.isEmpty()) {
          log.warn("NPM component not found: {}", component.getName() + "-" + component.getVersion());
        }

        String patchedVersion =
            StringUtils.isBlank(vulnerability.getPatchedIn()) ? N_A : vulnerability.getPatchedIn();
        boolean isAppIdAvailable = isNotBlank(packageLock.getRoot().getApplicationId());

        List<String> paths = resolvesForOneComponent.stream()
            .map(Resolve::getPath)
            .collect(toList());
        Advisory advisory = createAdvisory(index, component, vulnerability, patchedVersion, isAppIdAvailable);
        advisories.put(String.valueOf(index), advisory);
        resolvesForOneComponent.forEach(resolve -> actions.add(createAction(component, resolve, patchedVersion)));
        Set<Finding> findings = advisory.getFindings();
        Finding finding = new Finding(component.getVersion(), paths);
        findings.add(finding);
        index++;
      }
    }

    VulnerabilityReport vulnerabilityReport = createVulnerabilityReport(new ArrayList<>(advisories.values()));
    Metadata metadata = createMetadata(vulnerabilityReport, packageLock);
    return new ResponseReport(actions, advisories, muted, metadata);
  }

}