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 click.kamil.springstatemachineexporter.ast.common.CodebaseContext;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.io.TempDir;

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

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

/**
 * ENUM_SET on a call-edge argument must not be mistaken for a type FQN during path
 * type-compat checks (otherwise the edge is skipped and poly collapses to SYMBOLIC).
 */
class EnumSetCallEdgePathWalkTest {

    @Test
    void enumSetEdgeArgumentSurvivesPathWalkIntoPolymorphicEvents(@TempDir Path tempDir) throws Exception {
        Files.writeString(tempDir.resolve("OrderService.java"), """
                package com.example;
                public class OrderService {
                    public void updateOrderState(String vv) {
                        StateMachine sm = new StateMachine();
                        sm.sendEvent(getEventMultiValue(vv));
                    }

                    private OrderEvents getEventMultiValue(String q) {
                        return switch (q) {
                            case "a", "b" -> OrderEvents.A8;
                            case "c" -> OrderEvents.A133;
                            default -> OrderEvents.PAY;
                        };
                    }
                }
                enum OrderEvents { A8, A133, PAY }
                class StateMachine {
                    public void sendEvent(OrderEvents event) {}
                }
                """);
        CodebaseContext context = new CodebaseContext();
        context.scan(tempDir);
        HeuristicCallGraphEngine builder = new HeuristicCallGraphEngine(context);

        EntryPoint entryPoint = EntryPoint.builder()
                .className("com.example.OrderService")
                .methodName("updateOrderState")
                .build();
        TriggerPoint trigger = TriggerPoint.builder()
                .className("com.example.StateMachine")
                .methodName("sendEvent")
                .event("event")
                .build();
        List<CallChain> chains = builder.findChains(List.of(entryPoint), List.of(trigger));
        assertThat(chains).hasSize(1);
        assertThat(chains.get(0).getTriggerPoint().getPolymorphicEvents())
                .containsExactlyInAnyOrder("OrderEvents.A8", "OrderEvents.A133", "OrderEvents.PAY");
    }
}
