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.eventprocessing.plan.RuntimeProcessingExecutionApiRequest;
import at.procon.eventhub.processing.eventprocessing.plan.RuntimeProcessingExecutionResultDto;
import at.procon.eventhub.processing.eventprocessing.plan.RuntimeProcessingExecutionService;
import at.procon.eventhub.processing.eventprocessing.plan.RuntimeProcessingPlanDescriptorDto;
import at.procon.eventhub.processing.eventprocessing.validation.RuntimeMixedSourceEvidenceValidationApiRequest;
import at.procon.eventhub.processing.eventprocessing.validation.RuntimeMixedSourceEvidenceValidationResultDto;
import at.procon.eventhub.processing.eventprocessing.validation.RuntimeMixedSourceEvidenceValidationService;
import at.procon.eventhub.processing.eventprocessing.validation.RuntimeTachographParityValidationApiRequest;
import at.procon.eventhub.processing.eventprocessing.validation.RuntimeTachographParityValidationResultDto;
import at.procon.eventhub.processing.eventprocessing.validation.RuntimeTachographParityValidationService;
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.RuntimeDriverWorkingTimeScopeProcessingService;
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 RuntimeDriverWorkingTimeScopeProcessingService tachographEsperScopeProcessingService;
    private final RuntimeEventProcessingService runtimeEventProcessingService;
    private final RuntimeProcessingExecutionService runtimeProcessingExecutionService;
    private final RuntimeTachographParityValidationService tachographParityValidationService;
    private final RuntimeMixedSourceEvidenceValidationService mixedSourceEvidenceValidationService;

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

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

    @Autowired
    public UnifiedRuntimeProcessingController(
            UnifiedRuntimeEventAssemblyService eventAssemblyService,
            UnifiedRuntimeDriverTimelineService runtimeDriverTimelineService,
            UnifiedRuntimeDerivedProjectionService runtimeDerivedProjectionService,
            RuntimeDriverWorkingTimeScopeProcessingService tachographEsperScopeProcessingService,
            RuntimeEventProcessingService runtimeEventProcessingService,
            RuntimeTachographParityValidationService tachographParityValidationService,
            RuntimeMixedSourceEvidenceValidationService mixedSourceEvidenceValidationService,
            RuntimeProcessingExecutionService runtimeProcessingExecutionService
    ) {
        this.eventAssemblyService = eventAssemblyService;
        this.runtimeDriverTimelineService = runtimeDriverTimelineService;
        this.runtimeDerivedProjectionService = runtimeDerivedProjectionService;
        this.tachographEsperScopeProcessingService = tachographEsperScopeProcessingService;
        this.runtimeEventProcessingService = runtimeEventProcessingService;
        this.runtimeProcessingExecutionService = runtimeProcessingExecutionService;
        this.tachographParityValidationService = tachographParityValidationService;
        this.mixedSourceEvidenceValidationService = mixedSourceEvidenceValidationService;
    }

    public UnifiedRuntimeProcessingController(
            UnifiedRuntimeEventAssemblyService eventAssemblyService,
            UnifiedRuntimeDriverTimelineService runtimeDriverTimelineService,
            UnifiedRuntimeDerivedProjectionService runtimeDerivedProjectionService,
            RuntimeDriverWorkingTimeScopeProcessingService tachographEsperScopeProcessingService,
            RuntimeEventProcessingService runtimeEventProcessingService,
            RuntimeTachographParityValidationService tachographParityValidationService
    ) {
        this(eventAssemblyService, runtimeDriverTimelineService, runtimeDerivedProjectionService,
                tachographEsperScopeProcessingService, runtimeEventProcessingService,
                tachographParityValidationService, null, null);
    }

    @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("/executions/plans")
    public ResponseEntity<List<RuntimeProcessingPlanDescriptorDto>> listRuntimeProcessingPlans() {
        if (runtimeProcessingExecutionService == null) {
            throw new IllegalStateException("Runtime processing execution service is not configured.");
        }
        return ResponseEntity.ok(runtimeProcessingExecutionService.listPlans());
    }

    @PostMapping("/executions")
    public ResponseEntity<RuntimeProcessingExecutionResultDto> runRuntimeProcessingExecution(
            @RequestBody RuntimeProcessingExecutionApiRequest request
    ) {
        if (runtimeProcessingExecutionService == null) {
            throw new IllegalStateException("Runtime processing execution service is not configured.");
        }
        return ResponseEntity.ok(runtimeProcessingExecutionService.execute(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("/event-processing/validation/tachograph-parity")
    public ResponseEntity<RuntimeTachographParityValidationResultDto> validateTachographParity(
            @RequestBody RuntimeTachographParityValidationApiRequest request
    ) {
        if (tachographParityValidationService == null) {
            throw new IllegalStateException("Runtime tachograph parity validation service is not configured.");
        }
        return ResponseEntity.ok(tachographParityValidationService.validate(request));
    }


    @PostMapping("/event-processing/validation/mixed-source-evidence")
    public ResponseEntity<RuntimeMixedSourceEvidenceValidationResultDto> validateMixedSourceEvidence(
            @RequestBody RuntimeMixedSourceEvidenceValidationApiRequest request
    ) {
        if (mixedSourceEvidenceValidationService == null) {
            throw new IllegalStateException("Runtime mixed-source evidence validation service is not configured.");
        }
        return ResponseEntity.ok(mixedSourceEvidenceValidationService.validate(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(UnifiedRuntimeTachographEsperScopeResultDto.fromDriverWorkingTime(
                tachographEsperScopeProcessingService.processScope(request)
        ));
    }
}
