package at.procon.eventhub.tachograph.service;

import at.procon.eventhub.dto.EventSourceDto;
import at.procon.eventhub.importing.AbstractImportExecutionService;
import at.procon.eventhub.importing.ImportPlanDto;
import at.procon.eventhub.importing.ImportPlanItemDto;
import at.procon.eventhub.importing.ImportRunResultDto;
import at.procon.eventhub.importing.ImportTimeChunkDto;
import at.procon.eventhub.importing.persistence.ImportCursorRepository;
import at.procon.eventhub.importing.persistence.ImportRunRepository;
import at.procon.eventhub.persistence.DataPackageRepository;
import at.procon.eventhub.persistence.EventSourceRepository;
import at.procon.eventhub.tachograph.dto.TachographExtractionBatchResultDto;
import at.procon.eventhub.tachograph.dto.TachographImportRequest;
import at.procon.eventhub.tachograph.dto.TachographImportRunResultDto;
import java.util.Map;
import java.util.UUID;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
public class TachographImportExecutionService
        extends AbstractImportExecutionService<TachographImportRequest, TachographExtractionBatchResultDto> {

    private final TachographImportPlanService planService;
    private final TachographMasterDataRefreshService masterDataRefreshService;
    private final TachographExtractionBatchExecutor extractionBatchExecutor;

    public TachographImportExecutionService(
            TachographImportPlanService planService,
            EventSourceRepository eventSourceRepository,
            ImportRunRepository importRunRepository,
            DataPackageRepository dataPackageRepository,
            ImportCursorRepository importCursorRepository,
            TachographMasterDataRefreshService masterDataRefreshService,
            TachographExtractionBatchExecutor extractionBatchExecutor
    ) {
        super(eventSourceRepository, importRunRepository, dataPackageRepository, importCursorRepository);
        this.planService = planService;
        this.masterDataRefreshService = masterDataRefreshService;
        this.extractionBatchExecutor = extractionBatchExecutor;
    }

    @Transactional
    public TachographImportRunResultDto startImport(TachographImportRequest request) {
        return toTachographResult(createImportRun(request, false));
    }

    public TachographImportRunResultDto startAndExecuteImport(TachographImportRequest request) {
        return toTachographResult(createImportRun(request, true));
    }

    @Override
    protected ImportPlanDto createPlan(TachographImportRequest request) {
        return planService.createPlan(request);
    }

    @Override
    protected void beforeExecute(TachographImportRequest request) {
        masterDataRefreshService.refreshIfRequested(request);
    }

    @Override
    protected TachographExtractionBatchResultDto executeBatch(
            UUID importRunId,
            UUID packageId,
            int eventSourceId,
            TachographImportRequest request,
            ImportPlanItemDto planItem,
            ImportTimeChunkDto chunk
    ) {
        return extractionBatchExecutor.execute(importRunId, packageId, eventSourceId, request, planItem, chunk);
    }

    @Override
    protected EventSourceDto eventSourceForItem(EventSourceDto base, ImportPlanItemDto item) {
        String sourceKind = item.sourceKind();
        String sourceKey = switch (sourceKind) {
            case "VEHICLE_UNIT" -> "TACHOGRAPH_VEHICLE_UNIT";
            case "DRIVER_CARD" -> "TACHOGRAPH_DRIVER_CARD";
            default -> base.sourceKey();
        };
        return new EventSourceDto(
                base.providerKey(),
                sourceKind,
                sourceKey,
                base.sourceInstanceKey(),
                base.tenantProviderSettingKey(),
                base.externalFleetKey()
        );
    }

    @Override
    protected Map<String, Object> importRunMetadata(TachographImportRequest request, boolean executeImmediately) {
        return Map.of(
                "note", executeImmediately
                        ? "Created tachograph import run and executing planned extraction packages."
                        : "Created tachograph import run and planned extraction packages.",
                "packageModel", "EventHub data packages are extraction batches; original tachograph packages are SourcePackageRefDto.",
                "executeImmediately", executeImmediately
        );
    }

    @Override
    protected String providerPackagePrefix() {
        return "TACHOGRAPH";
    }

    @Override
    protected Map<String, Object> packageMetadata(
            TachographImportRequest request,
            ImportPlanItemDto item,
            ImportTimeChunkDto chunk,
            UUID importRunId
    ) {
        Map<String, Object> metadata = super.packageMetadata(request, item, chunk, importRunId);
        metadata.put("sourcePackageRefPolicy", "Original tachograph card/VU package is preserved per acquired event when SQL extraction returns it.");
        return metadata;
    }

    private TachographImportRunResultDto toTachographResult(ImportRunResultDto result) {
        return new TachographImportRunResultDto(
                result.importRunId(),
                result.status(),
                result.plannedPackageCount(),
                result.plan(),
                result.plannedPackageIds()
        );
    }
}
