package click.kamil.springstatemachineexporter.analysis.enricher;

import click.kamil.springstatemachineexporter.analysis.model.AnalysisResult;
import click.kamil.springstatemachineexporter.analysis.model.CallChain;
import click.kamil.springstatemachineexporter.analysis.model.CodebaseMetadata;
import click.kamil.springstatemachineexporter.analysis.model.TriggerPoint;
import click.kamil.springstatemachineexporter.model.Event;
import click.kamil.springstatemachineexporter.model.State;
import click.kamil.springstatemachineexporter.model.Transition;
import org.junit.jupiter.api.Test;

import java.util.List;

import static org.assertj.core.api.Assertions.assertThat;

class TransitionLinkerMultiSourceStateTest {

    @Test
    void shouldLinkEachSourceStatePairWithoutCrossMultiplication() {
        TriggerPoint trigger = TriggerPoint.builder()
                .event("com.example.OrderEvent.CANCEL")
                .sourceState("com.example.OrderState.PENDING")
                .build();
        CallChain chain = CallChain.builder()
                .entryPoint(click.kamil.springstatemachineexporter.analysis.model.EntryPoint.builder()
                        .type(click.kamil.springstatemachineexporter.analysis.model.EntryPoint.Type.REST)
                        .name("POST /cancel")
                        .className("com.example.Api")
                        .methodName("cancel")
                        .build())
                .triggerPoint(trigger)
                .methodChain(List.of("com.example.Api.cancel", "com.example.Service.fire"))
                .build();

        Transition fromPending = transition(
                "com.example.OrderEvent.CANCEL",
                "com.example.OrderState.PENDING",
                "com.example.OrderState.CANCELLED");
        Transition fromPaid = transition(
                "com.example.OrderEvent.CANCEL",
                "com.example.OrderState.PAID",
                "com.example.OrderState.CANCELLED");

        AnalysisResult result = AnalysisResult.builder()
                .name("com.example.config.OrderStateMachineConfiguration")
                .stateTypeFqn("com.example.OrderState")
                .eventTypeFqn("com.example.OrderEvent")
                .transitions(List.of(fromPending, fromPaid))
                .metadata(CodebaseMetadata.builder().callChains(List.of(chain)).build())
                .build();

        new TransitionLinkerEnricher().enrich(result, null, null);

        assertThat(result.getMetadata().getCallChains().get(0).getMatchedTransitions())
                .hasSize(1)
                .first()
                .satisfies(mt -> {
                    assertThat(mt.getSourceState()).isEqualTo("com.example.OrderState.PENDING");
                    assertThat(mt.getEvent()).isEqualTo("com.example.OrderEvent.CANCEL");
                });
    }

    private static Transition transition(String event, String source, String target) {
        Transition transition = new Transition();
        transition.setEvent(Event.of(event, event));
        transition.setSourceStates(List.of(
                State.of(source, source),
                State.of("com.example.OrderState.OTHER", "com.example.OrderState.OTHER")));
        transition.setTargetStates(List.of(State.of(target, target)));
        return transition;
    }
}
