package at.procon.eventhub.service;

import at.procon.eventhub.dto.EventDomain;
import at.procon.eventhub.dto.EventHubEventDto;
import at.procon.eventhub.dto.ImportScopeType;
import at.procon.eventhub.dto.SourceGroupType;
import org.springframework.stereotype.Component;

@Component
public class EventHubEventValidator {

    public void validate(EventHubEventDto event) {
        if (event == null) {
            throw new IllegalArgumentException("EventHubEventDto must not be null");
        }
        if (event.externalSourceEventId() == null || event.externalSourceEventId().isBlank()) {
            throw new IllegalArgumentException("externalSourceEventId must be set");
        }
        if (event.occurredAt() == null) {
            throw new IllegalArgumentException("occurredAt must be set");
        }
        boolean hasDriverRef = event.driverRef() != null && event.driverRef().hasAnyReference();
        boolean hasVehicleRef = event.vehicleRef() != null && event.vehicleRef().hasAnyReference();
        if (!hasDriverRef && !hasVehicleRef) {
            throw new IllegalArgumentException("driverRef or vehicleRef with at least one identifier must be set");
        }
        if (event.packageInfo() == null || event.packageInfo().tenantKey() == null || event.packageInfo().tenantKey().isBlank()) {
            throw new IllegalArgumentException("packageInfo.tenantKey must be set");
        }
        if (event.packageInfo().eventSource() == null) {
            throw new IllegalArgumentException("packageInfo.eventSource must be set");
        }
        validateImportScope(event);
        if (event.eventDomain() == null) {
            throw new IllegalArgumentException("eventDomain must be set");
        }
        if (event.eventType() == null) {
            throw new IllegalArgumentException("eventType must be set");
        }
        if (event.lifecycle() == null) {
            throw new IllegalArgumentException("lifecycle must be set");
        }
        if (event.position() != null && (event.position().latitude() == null || event.position().longitude() == null)) {
            throw new IllegalArgumentException("position latitude and longitude must both be set");
        }
        validateEventDetails(event);
    }

    private void validateImportScope(EventHubEventDto event) {
        var importScope = event.packageInfo().importScope();
        if (importScope == null) {
            throw new IllegalArgumentException("packageInfo.importScope must be set");
        }
        if (importScope.occurredFrom() != null && importScope.occurredTo() != null
                && !importScope.occurredFrom().isBefore(importScope.occurredTo())) {
            throw new IllegalArgumentException("importScope.occurredFrom must be before occurredTo");
        }
        if (importScope.type() == ImportScopeType.SOURCE_ORGANISATION_SUBTREE) {
            if (importScope.rootSourceOrganisation() == null
                    || importScope.rootSourceOrganisation().type() != SourceGroupType.ORGANISATION) {
                throw new IllegalArgumentException("SOURCE_ORGANISATION_SUBTREE requires rootSourceOrganisation.type=ORGANISATION");
            }
        }
    }

    private void validateEventDetails(EventHubEventDto event) {
        if (event.eventDetails() == null) {
            return;
        }
        String detailType = event.eventDetails().type();
        if (event.eventDomain() == EventDomain.DRIVER_ACTIVITY && !"DRIVER_ACTIVITY".equals(detailType)) {
            throw new IllegalArgumentException("DRIVER_ACTIVITY events must use eventDetails.type=DRIVER_ACTIVITY");
        }
        if (event.eventDomain() == EventDomain.BORDER_CROSSING && !"BORDER_CROSSING".equals(detailType)) {
            throw new IllegalArgumentException("BORDER_CROSSING events must use eventDetails.type=BORDER_CROSSING");
        }
        if (event.eventDomain() == EventDomain.POSITION && !"POSITION".equals(detailType)) {
            throw new IllegalArgumentException("POSITION events must use eventDetails.type=POSITION");
        }
        if (event.eventDomain() == EventDomain.PLACE && !"PLACE".equals(detailType)) {
            throw new IllegalArgumentException("PLACE events must use eventDetails.type=PLACE");
        }
        if (event.eventDomain() == EventDomain.LOAD_UNLOAD && !"LOAD_UNLOAD".equals(detailType)) {
            throw new IllegalArgumentException("LOAD_UNLOAD events must use eventDetails.type=LOAD_UNLOAD");
        }
        if (event.eventDomain() == EventDomain.SPECIFIC_CONDITION && !"SPECIFIC_CONDITION".equals(detailType)) {
            throw new IllegalArgumentException("SPECIFIC_CONDITION events must use eventDetails.type=SPECIFIC_CONDITION");
        }
        if (event.eventDomain() == EventDomain.SPEEDING && !"SPEEDING".equals(detailType)) {
            throw new IllegalArgumentException("SPEEDING events must use eventDetails.type=SPEEDING");
        }
    }
}
