package click.kamil.springstatemachineexporter.analysis;

import click.kamil.springstatemachineexporter.analysis.model.EntryPoint;
import click.kamil.springstatemachineexporter.analysis.resolver.ConstantResolver;
import click.kamil.springstatemachineexporter.analysis.service.SpringMvcDetector;
import click.kamil.springstatemachineexporter.ast.common.CodebaseContext;
import org.eclipse.jdt.core.dom.CompilationUnit;
import org.eclipse.jdt.core.dom.TypeDeclaration;
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 static org.assertj.core.api.Assertions.assertThat;

public class AdvancedEndpointResolutionTest {

    @Test
    void testComplexResolutionWithProfiles(@TempDir Path tempDir) throws IOException {
        Path srcDir = tempDir.resolve("src/main/java/com/example");
        Files.createDirectories(srcDir);
        
        // 1. Define Constants
        Files.writeString(srcDir.resolve("ApiConstants.java"),
            "package com.example;\n" +
            "public class ApiConstants {\n" +
            "    public static final String V1 = \"/v1\";\n" +
            "    public static final String BASE = \"${app.base:api}\" + V1;\n" +
            "}");

        // 2. Define Controller
        Files.writeString(srcDir.resolve("MyController.java"),
            "package com.example;\n" +
            "import org.springframework.web.bind.annotation.*;\n" +
            "import org.springframework.beans.factory.annotation.Value;\n" +
            "\n" +
            "@RestController\n" +
            "@RequestMapping(ApiConstants.BASE)\n" +
            "public class MyController {\n" +
            "    @Value(\"${app.suffix:/users}\")\n" +
            "    private String suffix;\n" +
            "\n" +
            "    @GetMapping(value = \"/list\" + \"${app.extra:}\")\n" +
            "    public void list() {}\n" +
            "    \n" +
            "    @PostMapping(\"${app.custom-path}\")\n" +
            "    public void custom() {}\n" +
            "}");

        // 3. Define Properties
        Files.writeString(tempDir.resolve("application.properties"), 
            "app.custom-path=/custom\n" +
            "app.base=core");
        
        Files.writeString(tempDir.resolve("application-prod.properties"), 
            "app.base=enterprise\n" +
            "app.extra=-premium");

        // --- SCENARIO 1: Default Profile ---
        CodebaseContext context = new CodebaseContext();
        context.scan(tempDir);

        SpringMvcDetector detector = new SpringMvcDetector(context, new ConstantResolver());
        TypeDeclaration controllerTd = context.getTypeDeclaration("com.example.MyController");
        CompilationUnit cu = (CompilationUnit) controllerTd.getRoot();
        
        List<EntryPoint> entryPoints = detector.detect(cu);
        
        // app.base=core, V1=/v1 => base path = /core/v1
        // list() => /core/v1/list
        // custom() => /core/v1/custom
        assertThat(entryPoints).hasSize(2);
        assertThat(entryPoints).anySatisfy(ep -> assertThat(ep.getName()).isEqualTo("GET /core/v1/list"));
        assertThat(entryPoints).anySatisfy(ep -> assertThat(ep.getName()).isEqualTo("POST /core/v1/custom"));

        // --- SCENARIO 2: Prod Profile ---
        context = new CodebaseContext();
        context.setActiveProfiles(List.of("prod"));
        context.scan(tempDir);

        detector = new SpringMvcDetector(context, new ConstantResolver());
        controllerTd = context.getTypeDeclaration("com.example.MyController");
        cu = (CompilationUnit) controllerTd.getRoot();

        entryPoints = detector.detect(cu);

        // app.base=enterprise (from prod), V1=/v1 => base path = /enterprise/v1
        // list() => /enterprise/v1/list-premium (app.extra from prod)
        // custom() => /enterprise/v1/custom
        assertThat(entryPoints).hasSize(2);
        assertThat(entryPoints).anySatisfy(ep -> assertThat(ep.getName()).isEqualTo("GET /enterprise/v1/list-premium"));
        assertThat(entryPoints).anySatisfy(ep -> assertThat(ep.getName()).isEqualTo("POST /enterprise/v1/custom"));
    }
}
