package click.kamil.springstatemachineexporter.analysis.service;

import click.kamil.springstatemachineexporter.analysis.model.EntryPoint;
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 static org.assertj.core.api.Assertions.assertThat;

class MessagingDetectorTest {

    @Test
    void shouldDetectRabbitListenerQueue(@TempDir Path tempDir) throws Exception {
        String source = """
            package com.example;
            import org.springframework.amqp.rabbit.annotation.RabbitListener;
            import org.springframework.stereotype.Component;
            @Component
            public class ReturnsListener {
                @RabbitListener(queues = "returns.queue")
                public void onReturn(String orderId) {}
            }
            """;
        Files.writeString(tempDir.resolve("ReturnsListener.java"), source);

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

        MessagingDetector detector = new MessagingDetector(context);
        org.eclipse.jdt.core.dom.TypeDeclaration td = context.getTypeDeclaration("com.example.ReturnsListener");
        List<EntryPoint> entryPoints = detector.detect((org.eclipse.jdt.core.dom.CompilationUnit) td.getRoot());

        assertThat(entryPoints).hasSize(1);
        assertThat(entryPoints.get(0).getType()).isEqualTo(EntryPoint.Type.RABBIT);
        assertThat(entryPoints.get(0).getName()).isEqualTo("RABBIT: returns.queue");
        assertThat(entryPoints.get(0).getMetadata()).containsEntry("destination", "returns.queue");
    }

    @Test
    void shouldDetectKafkaListenerTopicsAndTopicPattern(@TempDir Path tempDir) throws Exception {
        String source = """
            package com.example;
            import org.springframework.kafka.annotation.KafkaListener;
            import org.springframework.stereotype.Component;
            @Component
            public class OrderKafkaListener {
                @KafkaListener(topics = {"orders.created", "orders.updated"})
                public void onOrderEvent(String payload) {}

                @KafkaListener(topicPattern = "payments.*")
                public void onPaymentEvent(String payload) {}
            }
            """;
        Files.writeString(tempDir.resolve("OrderKafkaListener.java"), source);

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

        MessagingDetector detector = new MessagingDetector(context);
        org.eclipse.jdt.core.dom.TypeDeclaration td = context.getTypeDeclaration("com.example.OrderKafkaListener");
        List<EntryPoint> entryPoints = detector.detect((org.eclipse.jdt.core.dom.CompilationUnit) td.getRoot());

        assertThat(entryPoints).hasSize(2);
        assertThat(entryPoints).anyMatch(ep ->
                ep.getType() == EntryPoint.Type.KAFKA
                        && ep.getName().contains("orders.created")
                        && ep.getName().contains("orders.updated"));
        assertThat(entryPoints).anyMatch(ep ->
                ep.getType() == EntryPoint.Type.KAFKA
                        && "payments.*".equals(ep.getMetadata().get("destination")));
    }
}
