package com.airlock.iam.flow.infrastructure.mapper;

import ch.ergon.restal.jsonapi.document.data.CollectionDocument;
import com.airlock.iam.base.infrastructure.mapper.entity.IdSupplier;
import com.airlock.iam.base.infrastructure.mapper.entity.RestMapper;
import com.airlock.iam.flow.api.domain.model.flow.FlowResult;
import com.airlock.iam.flow.api.domain.model.step.StepResultDataCollection;
import com.airlock.iam.flow.api.infrastructure.mapper.FlowResultMapper;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import jakarta.ws.rs.core.Response;
import java.util.LinkedList;
import java.util.List;
import ma.glasnost.orika.MapperFacade;

public final class FlowResultToCollectionDocumentMapper {
   private final FlowResultMapper mapper;
   private final MapperFacade orikaMapper;

   public static FlowResultToCollectionDocumentMapper flowResultDataToCollectionDocumentMapper(FlowResultMapper mapper, MapperFacade mapperFacade) {
      return new FlowResultToCollectionDocumentMapper(mapper, mapperFacade);
   }

   public <E, C extends StepResultDataCollection<E>, T> Response map(
      FlowResult flowResult, Class<C> dataCollectionClass, Class<T> toClass, IdSupplier<E> idSupplier
   ) {
      if (flowResult.isFailed()) {
         return this.mapper.toResponse(flowResult);
      }

      List<E> elements = new LinkedList<>(flowResult.data(dataCollectionClass).get().getElements());
      RestMapper restMapper = new RestMapper(this.orikaMapper);
      CollectionDocument<T> document = restMapper.forElements(elements, toClass).withIdSupplier(idSupplier).toCollection();
      flowResult.metadata().forEach(document.getMeta()::addValue);
      return Response.ok(document).build();
   }

   @SuppressFBWarnings(justification = "generated code")
   public FlowResultToCollectionDocumentMapper(FlowResultMapper mapper, MapperFacade orikaMapper) {
      this.mapper = mapper;
      this.orikaMapper = orikaMapper;
   }
}
