package click.kamil.examples.enterprise.config;

import click.kamil.examples.enterprise.constants.OrderEvents;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.statemachine.config.EnableStateMachine;
import org.springframework.statemachine.config.StateMachineConfigurerAdapter;
import org.springframework.statemachine.config.builders.StateMachineStateConfigurer;
import org.springframework.statemachine.config.builders.StateMachineTransitionConfigurer;

@Configuration
@EnableStateMachine(name = "enterpriseStateMachine")
public class EnterpriseStateMachineConfig extends StateMachineConfigurerAdapter<String, String> {

    @Value("${order.initial.state:NEW}")
    private String initialState;

    @Override
    public void configure(StateMachineStateConfigurer<String, String> states) throws Exception {
        states
            .withStates()
                .initial(initialState)
                .state("PENDING_PAYMENT")
                .state("PAID")
                .state("SHIPPED")
                .choice("CHECK_AVAILABILITY")
                .end("CANCELLED")
                .end("RETURNED")
                .end("DELIVERED");
    }

    @Override
    public void configure(StateMachineTransitionConfigurer<String, String> transitions) throws Exception {
        transitions
            .withExternal()
                .source("NEW").target("CHECK_AVAILABILITY")
                .event(OrderEvents.PLACE)
            .and()
            .withChoice()
                .source("CHECK_AVAILABILITY")
                .first("PENDING_PAYMENT", (c) -> true)
                .last("CANCELLED")
            .and()
            .withExternal()
                .source("PENDING_PAYMENT").target("PAID")
                .event(OrderEvents.PAY)
            .and()
            .withExternal()
                .source("PAID").target("SHIPPED")
                .event(OrderEvents.SHIP)
            .and()
            .withExternal()
                .source("SHIPPED").target("DELIVERED")
                .event("FINALIZE")
            .and()
            .withExternal()
                .source("PAID").target("CANCELLED")
                .event(OrderEvents.CANCEL)
            .and()
            .withExternal()
                .source("DELIVERED").target("RETURNED")
                .event(OrderEvents.RETURN);
    }
}
