package click.kamil.springstatemachineexporter.analysis.service;

import click.kamil.springstatemachineexporter.analysis.model.CallChain;
import click.kamil.springstatemachineexporter.analysis.model.EntryPoint;
import click.kamil.springstatemachineexporter.analysis.model.TriggerPoint;
import org.junit.jupiter.api.io.TempDir;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.EnumSource;

import java.nio.file.Path;
import java.util.List;

import static click.kamil.springstatemachineexporter.analysis.service.CentralDispatcherTestSupport.EngineKind;
import static click.kamil.springstatemachineexporter.analysis.service.CentralDispatcherTestSupport.assertPolyEvents;
import static click.kamil.springstatemachineexporter.analysis.service.CentralDispatcherTestSupport.scanSource;
import static org.assertj.core.api.Assertions.assertThat;

class CustomMessageTriggerResolutionTest {

    private static final String SOURCE = """
            package com.example;
            enum OrderEvent { PROCESS, COMPLETE }
            class CustomStateMachineMessage<T, P> {
                CustomStateMachineMessage(T payload, P customPayload) {}
            }
            class StateMachineService {
                void sendCustomMessage(CustomStateMachineMessage<OrderEvent, String> customMessage) {}
            }
            class RabbitOrderListener {
                private StateMachineService stateMachineService;
                void handleCustomTransition(String payload) {
                    CustomStateMachineMessage<OrderEvent, String> customMessage =
                            new CustomStateMachineMessage<>(OrderEvent.PROCESS, "payload: " + payload);
                    stateMachineService.sendCustomMessage(customMessage);
                }
            }
            """;

    @ParameterizedTest
    @EnumSource(EngineKind.class)
    void customStateMachineMessageShouldExtractEventFromConstructor(EngineKind engineKind, @TempDir Path tempDir)
            throws Exception {
        var context = scanSource(SOURCE, tempDir);
        AbstractCallGraphEngine engine = engineKind == EngineKind.JDT
                ? new JdtCallGraphEngine(context, null)
                : new HeuristicCallGraphEngine(context);

        EntryPoint entryPoint = EntryPoint.builder()
                .className("com.example.RabbitOrderListener")
                .methodName("handleCustomTransition")
                .build();
        TriggerPoint trigger = TriggerPoint.builder()
                .className("com.example.StateMachineService")
                .methodName("sendCustomMessage")
                .event("customMessage")
                .build();

        List<CallChain> chains = engine.findChains(List.of(entryPoint), List.of(trigger));

        assertThat(chains).hasSize(1);
        assertPolyEvents(chains.get(0), "OrderEvent.PROCESS");
    }
}
