package at.procon.eventhub.processing.api;

import at.procon.eventhub.processing.dto.UnifiedRuntimeDerivedProjectionResultDto;
import at.procon.eventhub.processing.dto.UnifiedRuntimeProcessingApiRequest;
import at.procon.eventhub.processing.dto.UnifiedRuntimeTachographEsperScopeResultDto;
import at.procon.eventhub.processing.eventprocessing.RuntimeEventProcessingService;
import at.procon.eventhub.processing.eventprocessing.dto.RuntimeEventProcessingApiRequest;
import at.procon.eventhub.processing.eventprocessing.dto.RuntimeEventProcessingResultDto;
import at.procon.eventhub.processing.eventprocessing.dto.RuntimeEventProcessingProfileDescriptorDto;
import at.procon.eventhub.processing.model.UnifiedRuntimeEventBundle;
import at.procon.eventhub.processing.service.UnifiedRuntimeDerivedProjectionService;
import at.procon.eventhub.processing.service.UnifiedRuntimeDriverTimelineService;
import at.procon.eventhub.processing.service.UnifiedRuntimeEventAssemblyService;
import at.procon.eventhub.processing.service.UnifiedRuntimeTachographEsperScopeProcessingService;
import at.procon.eventhub.tachographfilesession.model.ResolvedDriverTimeline;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;

@RestController
@RequestMapping("/api/eventhub/runtime-processing")
public class UnifiedRuntimeProcessingController {

    private final UnifiedRuntimeEventAssemblyService eventAssemblyService;
    private final UnifiedRuntimeDriverTimelineService runtimeDriverTimelineService;
    private final UnifiedRuntimeDerivedProjectionService runtimeDerivedProjectionService;
    private final UnifiedRuntimeTachographEsperScopeProcessingService tachographEsperScopeProcessingService;
    private final RuntimeEventProcessingService runtimeEventProcessingService;

    public UnifiedRuntimeProcessingController(
            UnifiedRuntimeEventAssemblyService eventAssemblyService,
            UnifiedRuntimeDriverTimelineService runtimeDriverTimelineService,
            UnifiedRuntimeDerivedProjectionService runtimeDerivedProjectionService
    ) {
        this(eventAssemblyService, runtimeDriverTimelineService, runtimeDerivedProjectionService, null, null);
    }

    @Autowired
    public UnifiedRuntimeProcessingController(
            UnifiedRuntimeEventAssemblyService eventAssemblyService,
            UnifiedRuntimeDriverTimelineService runtimeDriverTimelineService,
            UnifiedRuntimeDerivedProjectionService runtimeDerivedProjectionService,
            UnifiedRuntimeTachographEsperScopeProcessingService tachographEsperScopeProcessingService,
            RuntimeEventProcessingService runtimeEventProcessingService
    ) {
        this.eventAssemblyService = eventAssemblyService;
        this.runtimeDriverTimelineService = runtimeDriverTimelineService;
        this.runtimeDerivedProjectionService = runtimeDerivedProjectionService;
        this.tachographEsperScopeProcessingService = tachographEsperScopeProcessingService;
        this.runtimeEventProcessingService = runtimeEventProcessingService;
    }

    @PostMapping("/driver-events")
    public ResponseEntity<UnifiedRuntimeEventBundle> loadDriverEvents(
            @RequestBody UnifiedRuntimeProcessingApiRequest request
    ) {
        return ResponseEntity.ok(eventAssemblyService.assembleDriverScopedEvents(request.toRuntimeRequest()));
    }

    @PostMapping("/driver-timeline")
    public ResponseEntity<ResolvedDriverTimeline> loadDriverTimeline(
            @RequestBody UnifiedRuntimeProcessingApiRequest request
    ) {
        return ResponseEntity.ok(runtimeDriverTimelineService.loadDriverTimeline(request.toRuntimeRequest()));
    }

    @PostMapping("/driver-derived-projections")
    public ResponseEntity<UnifiedRuntimeDerivedProjectionResultDto> loadDriverDerivedProjections(
            @RequestBody UnifiedRuntimeProcessingApiRequest request
    ) {
        return ResponseEntity.ok(runtimeDerivedProjectionService.loadDriverDerivedProjections(request));
    }

    @GetMapping("/event-processing/profiles")
    public ResponseEntity<List<RuntimeEventProcessingProfileDescriptorDto>> listEventProcessingProfiles() {
        if (runtimeEventProcessingService == null) {
            throw new IllegalStateException("Runtime event processing service is not configured.");
        }
        return ResponseEntity.ok(runtimeEventProcessingService.listProfiles());
    }

    @PostMapping("/event-processing")
    public ResponseEntity<RuntimeEventProcessingResultDto> runEventProcessing(
            @RequestBody RuntimeEventProcessingApiRequest request
    ) {
        if (runtimeEventProcessingService == null) {
            throw new IllegalStateException("Runtime event processing service is not configured.");
        }
        return ResponseEntity.ok(runtimeEventProcessingService.process(request));
    }

    @PostMapping("/tachograph/esper-processing")
    public ResponseEntity<UnifiedRuntimeTachographEsperScopeResultDto> runTachographEsperProcessing(
            @RequestBody UnifiedRuntimeProcessingApiRequest request
    ) {
        if (runtimeEventProcessingService != null) {
            RuntimeEventProcessingResultDto genericResult = runtimeEventProcessingService.process(
                    RuntimeEventProcessingApiRequest.tachographDriverEsper(request)
            );
            return ResponseEntity.ok(UnifiedRuntimeTachographEsperScopeResultDto.fromGenericRuntimeEventProcessingResult(genericResult));
        }
        if (tachographEsperScopeProcessingService == null) {
            throw new IllegalStateException("Tachograph Esper scope processing service is not configured.");
        }
        return ResponseEntity.ok(tachographEsperScopeProcessingService.processScope(request));
    }
}
