package p.studio.compiler.workspaces.stages;

import lombok.extern.slf4j.Slf4j;
import p.studio.compiler.backend.bytecode.BytecodeMarshalingException;
import p.studio.compiler.backend.bytecode.BytecodePreloadVerifierService;
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 VerifyBytecodePipelineStage implements PipelineStage {
    private final BytecodePreloadVerifierService verifierService;

    public VerifyBytecodePipelineStage() {
        this(new BytecodePreloadVerifierService());
    }

    VerifyBytecodePipelineStage(final BytecodePreloadVerifierService verifierService) {
        this.verifierService = verifierService;
    }

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

        try {
            verifierService.verify(ctx.bytecodeModule);
        } catch (BytecodeMarshalingException e) {
            return BuildingIssueSink.empty()
                    .report(builder -> builder
                            .error(true)
                            .phase("BACKEND_VERIFY_PRELOAD")
                            .code(e.code().name())
                            .message("[BUILD]: preload verifier failed: " + e.getMessage())
                            .exception(e));
        }

        return BuildingIssueSink.empty();
    }
}
