package com.airlock.iam.flow.domain.model.handover;

import com.airlock.iam.base.misc.log.LogUtil;
import com.airlock.iam.elog.api.ELogger;
import com.airlock.iam.elog.api.ELoggerFactory;
import com.airlock.iam.flow.api.domain.model.flow.FlowResult;
import com.airlock.iam.flow.domain.model.flow.handover.FlowHandover;
import com.airlock.iam.flow.domain.model.result.FlowResultImpl;
import com.airlock.iam.flow.domain.model.session.InternalFlowSession;
import com.airlock.iam.flow.domain.service.MultiFlowManager;
import jakarta.inject.Inject;

public class DefaultFlowHandover implements FlowHandover {
   private static final ELogger LOG = ELoggerFactory.getLogger(DefaultFlowHandover.class);
   private final MultiFlowManager multiFlowManager;

   @Inject
   public DefaultFlowHandover(MultiFlowManager multiFlowManager) {
      this.multiFlowManager = multiFlowManager;
   }

   @Override
   public FlowResult runNextFlowsIfPresent(FlowResult flowResult) {
      while (flowResult.flowCompletedSuccessfully() && this.multiFlowManager.shouldContinueWithNextFlow()) {
         flowResult = this.startNextFlow();
      }

      if (flowResult.flowCompletedSuccessfully() && !this.multiFlowManager.shouldContinueWithNextFlow()) {
         String multiFlowType = this.multiFlowManager.getCurrentMultiFlowType().map(type -> "type " + LogUtil.quote(type)).orElse("unknown type");
         LOG.info("No further flows to start, destroying multi-flow of " + multiFlowType + ".");
         this.multiFlowManager.destroyCurrentMultiFlow();
      }

      return flowResult;
   }

   private FlowResult startNextFlow() {
      LOG.info("Initiating new state machine for next flow");
      InternalFlowSession nextFlowSession = this.multiFlowManager.prepareNextFlowSession();
      this.multiFlowManager.startFlowSessionIfNotYetStarted();
      return FlowResultImpl.of(nextFlowSession.lastResult().get());
   }
}
