package click.kamil.springstatemachineexporter.analysis.service;

import click.kamil.springstatemachineexporter.analysis.model.CallEdge;
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 java.util.Map;

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

class CallGraphReceiverTypeQualificationTest {

    @Test
    void targetMethodClassMatchesReceiverTypeFqnAcrossPackages(@TempDir Path tempDir) throws Exception {
        Path webDir = tempDir.resolve("web");
        Path dispatchDir = tempDir.resolve("dispatch");
        Files.createDirectories(webDir);
        Files.createDirectories(dispatchDir);
        Files.writeString(webDir.resolve("Gateway.java"), """
            package com.example.web;
            import com.example.dispatch.CentralDispatcher;
            public class Gateway {
                private final CentralDispatcher centralEventDispatcher;
                public Gateway(CentralDispatcher centralEventDispatcher) {
                    this.centralEventDispatcher = centralEventDispatcher;
                }
                void execute(String command) {
                    centralEventDispatcher.dispatch(command);
                }
            }
            """);
        Files.writeString(dispatchDir.resolve("CentralDispatcher.java"), """
            package com.example.dispatch;
            public class CentralDispatcher {
                public void dispatch(String command) {}
            }
            """);

        CodebaseContext context = new CodebaseContext();
        context.setResolveBindings(true);
        context.scan(tempDir);
        HeuristicCallGraphEngine engine = new HeuristicCallGraphEngine(context);
        Map<String, List<CallEdge>> graph = engine.buildCallGraph();
        List<CallEdge> edges = graph.get("com.example.web.Gateway.execute");
        assertThat(edges).isNotEmpty();
        CallEdge dispatch = edges.stream()
                .filter(e -> e.getTargetMethod().endsWith(".dispatch"))
                .findFirst()
                .orElseThrow();
        assertThat(dispatch.getReceiverTypeFqn())
                .isEqualTo("com.example.dispatch.CentralDispatcher");
        assertThat(dispatch.getTargetMethod())
                .isEqualTo("com.example.dispatch.CentralDispatcher.dispatch");
    }
}
