package at.procon.eventhub.processing.eventprocessing.module;

import at.procon.eventhub.dto.EventHubEventDto;
import at.procon.eventhub.processing.driverworkingtime.model.DriverWorkingTimeVehicleUsageInterval;
import at.procon.eventhub.processing.eventprocessing.module.epl.DriverWorkingTimeEplEventMapper;
import at.procon.eventhub.processing.eventprocessing.module.epl.RuntimeEplInputEventStream;
import at.procon.eventhub.processing.eventprocessing.module.epl.RuntimeEplModule;
import at.procon.eventhub.processing.eventprocessing.module.epl.RuntimeEplModuleDefinition;
import at.procon.eventhub.processing.eventprocessing.module.epl.RuntimeEplModuleExecutionResult;
import at.procon.eventhub.processing.eventprocessing.module.epl.RuntimeEplModuleExecutor;
import at.procon.eventhub.processing.eventprocessing.plan.RuntimeProcessingModuleDescriptorDto;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class DriverVehicleUsageIntervalsModule implements RuntimeEplModule {

    public static final String OUTPUT_STATEMENT = "driverVehicleUsageIntervals";
    private static final String EPL_RESOURCE = "esper/runtime-driver-vehicle-usage-intervals.epl";

    private final RuntimeEplModuleExecutor eplModuleExecutor;

    @Autowired
    public DriverVehicleUsageIntervalsModule(RuntimeEplModuleExecutor eplModuleExecutor) {
        this.eplModuleExecutor = eplModuleExecutor;
    }

    /** Compatibility constructor for legacy tests that instantiate a local module registry. */
    public DriverVehicleUsageIntervalsModule() {
        this(new RuntimeEplModuleExecutor());
    }

    @Override
    public String moduleKey() {
        return DriverWorkingTimeModuleKeys.EVENT_TO_VEHICLE_USAGE_INTERVALS;
    }

    @Override
    public RuntimeProcessingModuleDescriptorDto descriptor() {
        return new RuntimeProcessingModuleDescriptorDto(
                moduleKey(),
                "Event to vehicle usage intervals",
                "EPL module that pairs canonical driver/card INSERT/WITHDRAW point events into source-neutral driver vehicle-usage intervals.",
                engine(),
                Set.of("DriverVehicleUsageIntervalEvent")
        );
    }

    @Override
    public RuntimeProcessingModuleResult execute(RuntimeProcessingModuleContext context) {
        List<EventHubEventDto> sourceEvents = DriverWorkingTimeEplEventMapper.sourceEvents(context);
        List<Map<String, Object>> pointEvents = DriverWorkingTimeEplEventMapper.vehicleUsagePointEvents(sourceEvents);
        RuntimeEplModuleExecutionResult eplResult = eplModuleExecutor.execute(new RuntimeEplModuleDefinition(
                moduleKey(),
                Map.of(
                        DriverWorkingTimeEplEventMapper.DRIVER_VEHICLE_USAGE_POINT_EVENT,
                        DriverWorkingTimeEplEventMapper.vehicleUsagePointEventDefinition()
                ),
                List.of(EPL_RESOURCE),
                List.of(OUTPUT_STATEMENT),
                List.of(new RuntimeEplInputEventStream(
                        DriverWorkingTimeEplEventMapper.DRIVER_VEHICLE_USAGE_POINT_EVENT,
                        pointEvents
                ))
        ));
        List<DriverWorkingTimeVehicleUsageInterval> intervals = eplResult.output(OUTPUT_STATEMENT).stream()
                .map(DriverWorkingTimeVehicleUsageInterval::fromMap)
                .toList();
        Map<String, Object> metadata = new LinkedHashMap<>(eplResult.metadata());
        metadata.put("inputEventCount", sourceEvents.size());
        metadata.put("vehicleUsagePointEventCount", pointEvents.size());
        metadata.put("vehicleUsageIntervalCount", intervals.size());
        return new RuntimeProcessingModuleResult(
                moduleKey(),
                RuntimeProcessingModuleStatus.SUCCESS,
                intervals,
                metadata,
                List.of()
        );
    }
}
