package click.kamil.springstatemachineexporter.analysis.service;

import click.kamil.springstatemachineexporter.ast.common.CodebaseContext;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.io.TempDir;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;

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

/**
 * Documents how traced call-path expressions are classified: map lookups vs bean getter chains.
 */
class CallGraphExpressionShapeTest {

    @TempDir
    Path tempDir;

    private HeuristicCallGraphEngine engine;
    private static final String SCOPE = "com.example.Service.handle";

    @BeforeEach
    void setUp() throws IOException {
        String source = """
                package com.example;

                import java.util.Map;
                import java.util.function.Supplier;

                public class Service {
                    private static final Map<String, String> ROUTES = Map.of("k", "v");
                    private EventWrapper eventWrapper;
                    private Supplier<String> eventSupplier;

                    public void handle(String commandKey) {
                        ROUTES.get(commandKey);
                        Routes.ROUTES.get(commandKey);
                        eventWrapper.getEvent();
                        eventSupplier.get();
                    }
                }

                class Routes {
                    static final Map<String, String> ROUTES = Map.of("k", "v");
                }

                class EventWrapper {
                    String getEvent() { return null; }
                }
                """;
        Files.writeString(tempDir.resolve("Service.java"), source);
        CodebaseContext context = new CodebaseContext();
        context.scan(tempDir);
        engine = new HeuristicCallGraphEngine(context);
    }

    @Test
    void extractMethodSuffixShouldKeepMapLookupIntact() {
        String[] parts = engine.extractMethodSuffix("ROUTES.get(commandKey)", "", SCOPE);
        assertThat(parts[0]).isEqualTo("ROUTES.get(commandKey)");
        assertThat(parts[1]).isEmpty();
    }

    @Test
    void extractMethodSuffixShouldKeepQualifiedMapLookupIntact() {
        String[] parts = engine.extractMethodSuffix("Routes.ROUTES.get(commandKey)", "", SCOPE);
        assertThat(parts[0]).isEqualTo("Routes.ROUTES.get(commandKey)");
        assertThat(parts[1]).isEmpty();
    }

    @Test
    void extractMethodSuffixShouldSplitBeanGetterChains() {
        String[] parts = engine.extractMethodSuffix("eventWrapper.getEvent()", "", SCOPE);
        assertThat(parts[0]).isEqualTo("eventWrapper");
        assertThat(parts[1]).isEqualTo(".getEvent()");
    }

    @Test
    void extractMethodSuffixShouldSplitNoArgGetCalls() {
        String[] parts = engine.extractMethodSuffix("eventSupplier.get()", "", SCOPE);
        assertThat(parts[0]).isEqualTo("eventSupplier");
        assertThat(parts[1]).isEqualTo(".get()");
    }

    @Test
    void extractMethodSuffixShouldSplitChainedBeanGetters() {
        String[] parts = engine.extractMethodSuffix("this.eventWrapper.getEvent().name()", ".name()", SCOPE);
        assertThat(parts[0]).isEqualTo("this.eventWrapper");
        assertThat(parts[1]).startsWith(".getEvent()");
    }
}
