package at.procon.eventhub.tachograph.api;

import at.procon.eventhub.dto.AcquisitionStrategy;
import at.procon.eventhub.dto.ImportMode;
import at.procon.eventhub.dto.SchedulerTriggerMode;
import at.procon.eventhub.importing.masterdata.MasterDataRefreshResult;
import at.procon.eventhub.tachograph.dto.ConfiguredTachographImportPlanDto;
import at.procon.eventhub.tachograph.dto.TachographImportRequest;
import at.procon.eventhub.tachograph.dto.TachographImportRunResultDto;
import at.procon.eventhub.tachograph.dto.TachographImportTriggerResultDto;
import at.procon.eventhub.tachograph.dto.source.TachographActivityDto;
import at.procon.eventhub.tachograph.service.TachographConfiguredImportPlanService;
import at.procon.eventhub.tachograph.service.TachographImportExecutionService;
import at.procon.eventhub.tachograph.service.TachographImportPlanService;
import at.procon.eventhub.tachograph.service.TachographMasterDataRefreshService;
import jakarta.validation.Valid;
import java.time.OffsetDateTime;
import java.util.List;
import java.util.Map;
import org.apache.camel.ProducerTemplate;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
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.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/api/eventhub/acquisition/tachograph")
public class TachographIngestionController {

    private final ProducerTemplate producerTemplate;
    private final TachographImportPlanService tachographImportPlanService;
    private final TachographConfiguredImportPlanService configuredImportPlanService;
    private final TachographImportExecutionService tachographImportExecutionService;
    private final TachographMasterDataRefreshService masterDataRefreshService;

    public TachographIngestionController(
            ProducerTemplate producerTemplate,
            TachographImportPlanService tachographImportPlanService,
            TachographConfiguredImportPlanService configuredImportPlanService,
            TachographImportExecutionService tachographImportExecutionService,
            TachographMasterDataRefreshService masterDataRefreshService
    ) {
        this.producerTemplate = producerTemplate;
        this.tachographImportPlanService = tachographImportPlanService;
        this.configuredImportPlanService = configuredImportPlanService;
        this.tachographImportExecutionService = tachographImportExecutionService;
        this.masterDataRefreshService = masterDataRefreshService;
    }

    @PostMapping("/activities")
    public ResponseEntity<Map<String, Object>> ingestTachographActivities(@RequestBody List<TachographActivityDto> activities) {
        producerTemplate.sendBody("direct:tachograph-activity-input", activities);
        return accepted(activities.size(), "direct:tachograph-activity-input");
    }

    @PostMapping("/imports/plan")
    public ResponseEntity<?> planTachographImport(@Valid @RequestBody TachographImportRequest request) {
        return ResponseEntity.ok(tachographImportPlanService.createPlan(request));
    }

    @PostMapping("/imports/start")
    public ResponseEntity<TachographImportRunResultDto> startTachographImport(
            @Valid @RequestBody TachographImportRequest request,
            @RequestParam(defaultValue = "false") boolean execute
    ) {
        TachographImportRunResultDto result = execute
                ? tachographImportExecutionService.startAndExecuteImport(request)
                : producerTemplate.requestBody("direct:tachograph-import-start", request, TachographImportRunResultDto.class);
        return ResponseEntity.accepted().body(result);
    }

    @PostMapping("/master-data/refresh")
    public ResponseEntity<MasterDataRefreshResult> refreshTachographMasterData(
            @Valid @RequestBody TachographImportRequest request
    ) {
        return ResponseEntity.ok(masterDataRefreshService.refresh(request));
    }

    @GetMapping("/imports/configured-plans")
    public ResponseEntity<List<ConfiguredTachographImportPlanDto>> listConfiguredTachographPlans() {
        return ResponseEntity.ok(configuredImportPlanService.listPlans());
    }

    @GetMapping("/imports/configured-plans/{planKey}")
    public ResponseEntity<ConfiguredTachographImportPlanDto> getConfiguredTachographPlan(@PathVariable String planKey) {
        return ResponseEntity.ok(configuredImportPlanService.getPlan(planKey));
    }

    @PostMapping("/imports/configured-plans/{planKey}/start")
    public ResponseEntity<TachographImportTriggerResultDto> startConfiguredTachographPlan(
            @PathVariable String planKey,
            @RequestParam(required = false) ImportMode mode,
            @RequestParam(required = false) AcquisitionStrategy strategy,
            @RequestParam(defaultValue = "PLAN_ONLY") SchedulerTriggerMode triggerMode
    ) {
        TachographImportRequest request = configuredImportPlanService.createRequest(planKey, mode, strategy);
        TachographImportRunResultDto result = triggerMode == SchedulerTriggerMode.EXECUTE
                ? tachographImportExecutionService.startAndExecuteImport(request)
                : tachographImportExecutionService.startImport(request);
        return ResponseEntity.accepted().body(new TachographImportTriggerResultDto(
                planKey,
                request.mode(),
                request.acquisitionStrategy(),
                triggerMode,
                OffsetDateTime.now(),
                result
        ));
    }

    @PostMapping("/imports/configured-plans/{planKey}/master-data/refresh")
    public ResponseEntity<MasterDataRefreshResult> refreshConfiguredTachographMasterData(
            @PathVariable String planKey,
            @RequestParam(required = false) ImportMode mode,
            @RequestParam(required = false) AcquisitionStrategy strategy
    ) {
        TachographImportRequest request = configuredImportPlanService.createRequest(planKey, mode, strategy);
        return ResponseEntity.ok(masterDataRefreshService.refresh(request));
    }

    private ResponseEntity<Map<String, Object>> accepted(int count, String route) {
        return ResponseEntity.accepted().body(Map.of(
                "accepted", count,
                "route", route,
                "note", "Events are accepted into Camel acquisition routes, grouped by EventSource/package context, sorted in each batch, and then handed to the current ingestion adapter."
        ));
    }
}
