package com.airlock.iam.flow.domain.model.statemachine.spring;

import com.airlock.iam.flow.api.domain.model.step.FlowStep;
import com.airlock.iam.flow.api.domain.model.step.StepResult;
import com.airlock.iam.flow.domain.model.event.StateMachineFlowEvent;
import com.airlock.iam.flow.domain.model.statemachine.FlowState;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import jakarta.inject.Provider;
import lombok.NonNull;
import org.springframework.statemachine.StateContext;
import org.springframework.statemachine.action.Action;

public class CurrentAndNextStepAction implements Action<FlowState, StateMachineFlowEvent> {
   @NonNull
   private final CurrentAndNextStepAction.CurrentAndNextStepHandler handler;
   @NonNull
   private final Provider<FlowStep> step;
   @NonNull
   private final Provider<FlowStep> nextStep;

   public void execute(StateContext<FlowState, StateMachineFlowEvent> context) {
      StepResult stepResultToBeProcessed = StepResultExtractor.extractStepResult(context);
      this.handler.execute((FlowStep)this.step.get(), stepResultToBeProcessed, (FlowStep)this.nextStep.get());
   }

   public static CurrentAndNextStepAction currentAndNextStepAction(
      CurrentAndNextStepAction.CurrentAndNextStepHandler handler, StepContext step, StepContext nextStep
   ) {
      return new CurrentAndNextStepAction(handler, step.getStep(), nextStep.getStep());
   }

   @SuppressFBWarnings(justification = "generated code")
   private CurrentAndNextStepAction(
      @NonNull CurrentAndNextStepAction.CurrentAndNextStepHandler handler, @NonNull Provider<FlowStep> step, @NonNull Provider<FlowStep> nextStep
   ) {
      if (handler == null) {
         throw new NullPointerException("handler is marked non-null but is null");
      }

      if (step == null) {
         throw new NullPointerException("step is marked non-null but is null");
      }

      if (nextStep == null) {
         throw new NullPointerException("nextStep is marked non-null but is null");
      }

      this.handler = handler;
      this.step = step;
      this.nextStep = nextStep;
   }

   @FunctionalInterface
   public interface CurrentAndNextStepHandler {
      void execute(FlowStep var1, StepResult var2, FlowStep var3);
   }
}
