package click.kamil.springstatemachineexporter.analysis.service;

import click.kamil.springstatemachineexporter.exporter.JsonExporter;
import click.kamil.springstatemachineexporter.service.ExportService;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
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;

/**
 * End-to-end verification for {@code state_machines/inheritance_sample}:
 * interface-mapped REST → injected service impl → {@code sendEvent}.
 */
class InheritanceSampleChainTest {

    private static Path findProjectRoot() {
        Path current = Path.of(".").toAbsolutePath();
        while (current != null && !Files.exists(current.resolve("settings.gradle"))) {
            current = current.getParent();
        }
        return current;
    }

    @Test
    void exportShouldIncludeTriggerAndCallChain(@TempDir Path tempDir) throws Exception {
        Path sampleRoot = findProjectRoot().resolve("state_machines/inheritance_sample");

        ExportService exportService = new ExportService(List.of(new JsonExporter()));
        exportService.runExporter(sampleRoot, tempDir, List.of("json"), true, List.of(), null, null,
                click.kamil.springstatemachineexporter.exporter.EnumFormat.fn,
                click.kamil.springstatemachineexporter.exporter.EnumFormat.fn);

        ObjectMapper mapper = new ObjectMapper();
        Path jsonFile;
        try (var stream = Files.walk(tempDir)) {
            jsonFile = stream.filter(p -> p.getFileName().toString().contains("InheritanceStateMachineConfig")
                    && p.getFileName().toString().endsWith(".json")).findFirst().orElseThrow();
        }
        JsonNode metadata = mapper.readTree(jsonFile.toFile()).path("metadata");

        assertThat(metadata.path("triggers").size()).as("triggers").isGreaterThan(0);
        assertThat(metadata.path("callChains").size()).as("callChains").isGreaterThan(0);

        JsonNode chain = metadata.path("callChains").get(0);
        assertThat(chain.path("entryPoint").path("name").asText())
                .isEqualTo("POST /api/v2/orders/submit");
        assertThat(chain.path("methodChain").toString())
                .contains("OrderControllerImpl.submitOrder")
                .contains("ProcessingServiceImpl.doProcess");
        assertThat(chain.path("triggerPoint").path("event").asText())
                .isIn("INHERITED_SUBMIT", "java.lang.String.INHERITED_SUBMIT", "String.INHERITED_SUBMIT");
        assertThat(chain.path("matchedTransitions").size()).isEqualTo(1);
    }
}
