package click.kamil.enterprise.web;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.statemachine.StateMachine;
import org.springframework.statemachine.config.StateMachineFactory;
import org.springframework.stereotype.Service;

import click.kamil.enterprise.machines.order.OrderEvent;
import click.kamil.enterprise.machines.order.OrderState;
import click.kamil.enterprise.machines.document.DocumentEvent;
import click.kamil.enterprise.machines.document.DocumentState;
import click.kamil.enterprise.machines.user.UserEvent;
import click.kamil.enterprise.machines.user.UserState;

@Service
public class StateMachineDispatcher {

    @Autowired
    private StateMachineFactory<OrderState, OrderEvent> orderStateMachineFactory;
    
    @Autowired
    private StateMachineFactory<DocumentState, DocumentEvent> documentStateMachineFactory;
    
    @Autowired
    private StateMachineFactory<UserState, UserEvent> userStateMachineFactory;

    public String payOrder(String userId) {
        StateMachine<OrderState, OrderEvent> machine = orderStateMachineFactory.getStateMachine();
        machine.start();
        machine.sendEvent(OrderEvent.PAY);
        return "Order paid by " + userId;
    }

    public String shipOrder(String userId) {
        StateMachine<OrderState, OrderEvent> machine = orderStateMachineFactory.getStateMachine();
        machine.start();
        machine.sendEvent(OrderEvent.SHIP);
        return "Order shipped by " + userId;
    }

    public String submitDocument(String userId) {
        StateMachine<DocumentState, DocumentEvent> machine = documentStateMachineFactory.getStateMachine();
        machine.start();
        machine.sendEvent(DocumentEvent.SUBMIT);
        return "Document submitted by " + userId;
    }

    public String approveDocument(String userId) {
        StateMachine<DocumentState, DocumentEvent> machine = documentStateMachineFactory.getStateMachine();
        machine.start();
        machine.sendEvent(DocumentEvent.APPROVE);
        return "Document approved by " + userId;
    }

    public String rejectDocument(String userId) {
        StateMachine<DocumentState, DocumentEvent> machine = documentStateMachineFactory.getStateMachine();
        machine.start();
        machine.sendEvent(DocumentEvent.REJECT);
        return "Document rejected by " + userId;
    }

    public String verifyUser(String userId) {
        StateMachine<UserState, UserEvent> machine = userStateMachineFactory.getStateMachine();
        machine.start();
        machine.sendEvent(UserEvent.VERIFY);
        return "User verified: " + userId;
    }

    public String suspendUser(String userId) {
        StateMachine<UserState, UserEvent> machine = userStateMachineFactory.getStateMachine();
        machine.start();
        machine.sendEvent(UserEvent.SUSPEND);
        return "User suspended: " + userId;
    }

    public String dispatch(String machineType, String eventString) {
        if ("ORDER".equalsIgnoreCase(machineType)) {
            StateMachine<OrderState, OrderEvent> machine = orderStateMachineFactory.getStateMachine();
            machine.start();
            OrderEvent event = OrderEvent.valueOf(eventString.toUpperCase());
            machine.sendEvent(event);
            return "Triggered " + event;
        } else if ("DOCUMENT".equalsIgnoreCase(machineType)) {
            StateMachine<DocumentState, DocumentEvent> machine = documentStateMachineFactory.getStateMachine();
            machine.start();
            DocumentEvent event = DocumentEvent.valueOf(eventString.toUpperCase());
            machine.sendEvent(event);
            return "Triggered " + event;
        } else if ("USER".equalsIgnoreCase(machineType)) {
            StateMachine<UserState, UserEvent> machine = userStateMachineFactory.getStateMachine();
            machine.start();
            UserEvent event = UserEvent.valueOf(eventString.toUpperCase());
            machine.sendEvent(event);
            return "Triggered " + event;
        }
        throw new IllegalArgumentException("Unknown machine type: " + machineType);
    }
}
