package click.kamil.springstatemachineexporter.analysis.service;

import click.kamil.springstatemachineexporter.analysis.resolver.ConstantResolver;
import click.kamil.springstatemachineexporter.ast.common.CodebaseContext;
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 java.util.List;
import java.util.Map;

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

class VariableTracerTest {

    @Test
    void shouldShortCircuitLiteralStringResolution() {
        CodebaseContext context = new CodebaseContext();
        VariableTracer tracer = new VariableTracer(context, new ConstantResolver());

        // Even with an empty context and call graph, passing a raw String literal should return instantly
        // without trying to recursively traverse the path or crash.
        String resolved = tracer.resolveArgumentValue("\"PAY_EVENT\"", "com.example.Order.process", List.of("com.example.Order.process"), 0, Map.of());
        
        assertThat(resolved).isEqualTo("\"PAY_EVENT\"");
    }

    @Test
    void shouldBridgePolymorphicParametersPositionally(@TempDir Path tempDir) throws IOException {
        Path comFoo = tempDir.resolve("com/foo");
        Files.createDirectories(comFoo);
        
        // Setup an interface and implementation with DIFFERENT parameter names
        Files.writeString(comFoo.resolve("PaymentService.java"),
            "package com.foo;\n" +
            "public interface PaymentService {\n" +
            "    void submit(String eventName);\n" +
            "}"
        );
        Files.writeString(comFoo.resolve("PaymentServiceImpl.java"),
            "package com.foo;\n" +
            "public class PaymentServiceImpl implements PaymentService {\n" +
            "    @Override\n" +
            "    public void submit(String e) {}\n" +
            "}"
        );

        CodebaseContext context = new CodebaseContext();
        context.scan(tempDir);

        VariableTracer tracer = new VariableTracer(context, new ConstantResolver());

        // Simulate tracing from the Interface backwards to the Implementation.
        // Because this is a polymorphic bridge, there is NO direct call edge in the AST call graph.
        Map<String, String> params = tracer.buildParameterValuesMap(
                "com.foo.PaymentService.submit", 
                "com.foo.PaymentServiceImpl.submit", 
                Map.of(), // Empty call graph (no direct edges)
                List.of("com.foo.PaymentService.submit", "com.foo.PaymentServiceImpl.submit"), 
                0
        );

        // The tracer should have scanned both ASTs and mapped parameter 0 -> parameter 0
        assertThat(params).hasSize(1);
        assertThat(params).containsEntry("e", "eventName");
    }
}
