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

import at.procon.eventhub.dto.EventHubEventDto;
import at.procon.eventhub.processing.driverworkingtime.model.DriverWorkingTimeActivityInterval;
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 DriverActivityIntervalsModule implements RuntimeEplModule {

    public static final String OUTPUT_STATEMENT = "driverActivityIntervals";
    private static final String EPL_RESOURCE = "esper/runtime-driver-activity-intervals.epl";

    private final RuntimeEplModuleExecutor eplModuleExecutor;

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

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

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

    @Override
    public RuntimeProcessingModuleDescriptorDto descriptor() {
        return new RuntimeProcessingModuleDescriptorDto(
                moduleKey(),
                "Event to activity intervals",
                "EPL module that pairs canonical DRIVER_ACTIVITY START/END point events into source-neutral driver activity intervals.",
                engine(),
                Set.of("DriverActivityIntervalEvent")
        );
    }

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