package p.studio.compiler.workspaces.stages;

import lombok.extern.slf4j.Slf4j;
import p.studio.compiler.backend.bytecode.BytecodeLinkPrecheckService;
import p.studio.compiler.backend.bytecode.BytecodeMarshalingException;
import p.studio.compiler.messages.BuildingIssueSink;
import p.studio.compiler.models.BuilderPipelineContext;
import p.studio.compiler.workspaces.PipelineStage;
import p.studio.utilities.logs.LogAggregator;

@Slf4j
public class LinkBytecodePipelineStage implements PipelineStage {
    private final BytecodeLinkPrecheckService linkPrecheckService;

    public LinkBytecodePipelineStage() {
        this(new BytecodeLinkPrecheckService());
    }

    LinkBytecodePipelineStage(final BytecodeLinkPrecheckService linkPrecheckService) {
        this.linkPrecheckService = linkPrecheckService;
    }

    @Override
    public BuildingIssueSink run(BuilderPipelineContext ctx, LogAggregator logs) {
        if (ctx.bytecodeModule == null) {
            return BuildingIssueSink.empty()
                    .report(builder -> builder
                            .error(true)
                            .phase("BACKEND_LINK_PRECHECK")
                            .code("MARSHAL_FORMAT_STAGE_INPUT_MISSING")
                            .message("[BUILD]: bytecode module is missing before LinkBytecode stage"));
        }

        try {
            linkPrecheckService.validate(ctx.bytecodeModule);
        } catch (BytecodeMarshalingException e) {
            return BuildingIssueSink.empty()
                    .report(builder -> builder
                            .error(true)
                            .phase("BACKEND_LINK_PRECHECK")
                            .code(e.code().name())
                            .message("[BUILD]: bytecode link precheck failed: " + e.getMessage())
                            .exception(e));
        }

        return BuildingIssueSink.empty();
    }
}
