package p.studio.compiler.workspaces.stages;

import lombok.extern.slf4j.Slf4j;
import p.studio.compiler.backend.irvm.IRVMValidationException;
import p.studio.compiler.backend.irvm.OptimizeIRVMService;
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 OptimizeIRVMPipelineStage implements PipelineStage {
    private final OptimizeIRVMService optimizeIRVMService;

    public OptimizeIRVMPipelineStage() {
        this(new OptimizeIRVMService());
    }

    OptimizeIRVMPipelineStage(final OptimizeIRVMService optimizeIRVMService) {
        this.optimizeIRVMService = optimizeIRVMService;
    }

    @Override
    public BuildingIssueSink run(BuilderPipelineContext ctx, LogAggregator logs) {
        if (ctx.irvm == null) {
            return BuildingIssueSink.empty()
                    .report(builder -> builder
                            .error(true)
                            .phase("BACKEND_OPTIMIZE_IRVM")
                            .code("MARSHAL_FORMAT_STAGE_INPUT_MISSING")
                            .message("[BUILD]: IRVM is missing before OptimizeIRVM stage"));
        }
        try {
            ctx.optimizedIrvm = optimizeIRVMService.optimize(ctx.irvm);
        } catch (IRVMValidationException e) {
            return BuildingIssueSink.empty()
                    .report(builder -> builder
                            .error(true)
                            .phase("BACKEND_OPTIMIZE_IRVM")
                            .code(e.code().name())
                            .functionIndex(e.functionIndex())
                            .pc(e.pc())
                            .message("[BUILD]: optimize irvm validation failed: " + e.getMessage())
                            .exception(e));
        } catch (RuntimeException e) {
            return BuildingIssueSink.empty()
                    .report(builder -> builder
                            .error(true)
                            .phase("BACKEND_OPTIMIZE_IRVM")
                            .code("MARSHAL_VERIFY_PRECHECK_OPTIMIZE_RUNTIME_FAILURE")
                            .message("[BUILD]: optimize irvm failed: " + e.getMessage())
                            .exception(e));
        }
        return BuildingIssueSink.empty();
    }
}
