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.nio.file.Files;
import java.nio.file.Path;
import java.util.Map;

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

class PathBindingExpressionResolverTest {

    private CodebaseContext context;
    private PathBindingExpressionResolver resolver;

    @BeforeEach
    void setUp(@TempDir Path tempDir) throws Exception {
        String source = """
            package com.example;
            enum DomainCommand { ORDER_PAY, ORDER_SHIP }
            class CommandGateway {
                private final StringCommandMapper mapper = new StringCommandMapper();
                void executeViaMapper(String commandKey) {
                    DomainCommand command = mapper.fromString(commandKey);
                    dispatch(command);
                }
                void dispatch(DomainCommand command) {}
            }
            class StringCommandMapper {
                DomainCommand fromString(String commandKey) {
                    return switch (commandKey) {
                        case "order.pay" -> DomainCommand.ORDER_PAY;
                        case "order.ship" -> DomainCommand.ORDER_SHIP;
                        default -> throw new IllegalArgumentException(commandKey);
                    };
                }
            }
            """;
        Files.writeString(tempDir.resolve("App.java"), source);

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

        VariableTracer variableTracer = new VariableTracer(context, context.getConstantResolver());
        resolver = new PathBindingExpressionResolver(context, variableTracer, context.getConstantResolver());
    }

    @Test
    void shouldResolveMapperFromStringViaDataflowWithNamedBindings() {
        String resolved = resolver.resolveMethodCallFromSource(
                "com.example.CommandGateway.executeViaMapper",
                "command",
                Map.of("commandKey", "order.pay"));

        assertThat(resolved).isEqualTo("DomainCommand.ORDER_PAY");
    }

    @Test
    void shouldResolveAlternateSwitchArmViaDataflowNamedBindings() {
        String resolved = resolver.resolveMethodCallFromSource(
                "com.example.CommandGateway.executeViaMapper",
                "command",
                Map.of("commandKey", "order.ship"));

        assertThat(resolved).isEqualTo("DomainCommand.ORDER_SHIP");
    }
}
