package p.studio.compiler.workspaces;

import org.junit.jupiter.api.Test;
import p.studio.compiler.workspaces.stages.EmitBytecodePipelineStage;
import p.studio.compiler.workspaces.stages.FrontendPhasePipelineStage;
import p.studio.compiler.workspaces.stages.LinkBytecodePipelineStage;
import p.studio.compiler.workspaces.stages.LoadSourcesPipelineStage;
import p.studio.compiler.workspaces.stages.LowerToIRVMPipelineStage;
import p.studio.compiler.workspaces.stages.OptimizeIRVMPipelineStage;
import p.studio.compiler.workspaces.stages.ResolveDepsPipelineStage;
import p.studio.compiler.workspaces.stages.VerifyBytecodePipelineStage;
import p.studio.compiler.workspaces.stages.WriteBytecodeArtifactPipelineStage;

import java.lang.reflect.Field;
import java.util.List;

import static org.junit.jupiter.api.Assertions.assertEquals;

class BuilderPipelineServiceOrderTest {

    @Test
    void canonicalOrderMustContainOptimizeBetweenLowerAndEmit() throws Exception {
        final Field field = BuilderPipelineService.class.getDeclaredField("stages");
        field.setAccessible(true);

        @SuppressWarnings("unchecked")
        final var stages = (List<PipelineStage>) field.get(BuilderPipelineService.INSTANCE);
        final var stageTypes = stages.stream().map(Object::getClass).toList();

        assertEquals(
                List.of(
                        ResolveDepsPipelineStage.class,
                        LoadSourcesPipelineStage.class,
                        FrontendPhasePipelineStage.class,
                        LowerToIRVMPipelineStage.class,
                        OptimizeIRVMPipelineStage.class,
                        EmitBytecodePipelineStage.class,
                        LinkBytecodePipelineStage.class,
                        VerifyBytecodePipelineStage.class,
                        WriteBytecodeArtifactPipelineStage.class),
                stageTypes);
    }
}
