package at.procon.eventhub.processing.support;

import at.procon.eventhub.dto.DriverCardRefDto;
import at.procon.eventhub.dto.DriverRefDto;
import at.procon.eventhub.dto.EventHubEventDto;
import at.procon.eventhub.dto.VehicleRefDto;
import at.procon.eventhub.dto.VehicleRegistrationRefDto;
import at.procon.eventhub.processing.model.UnifiedRuntimeProcessingRequest;
import com.fasterxml.jackson.databind.JsonNode;
import java.util.List;

public final class TachographRuntimeIdentityResolver {

    private TachographRuntimeIdentityResolver() {
    }

    public static String driverKey(EventHubEventDto event) {
        JsonNode raw = rawPayload(event);
        String rawDriverKey = firstNonBlank(text(raw, "driverKey"), text(raw, "driverCardKey"));
        if (rawDriverKey != null) {
            return rawDriverKey;
        }
        DriverRefDto driverRef = event == null ? null : event.driverRef();
        DriverCardRefDto driverCard = driverRef == null ? null : driverRef.driverCard();
        return driverCard != null && driverCard.hasValue() ? normalize(driverCard.stableKey()) : null;
    }

    public static String registrationKey(EventHubEventDto event) {
        JsonNode raw = rawPayload(event);
        String rawRegistrationKey = canonicalRegistrationKey(text(raw, "registrationKey"));
        if (rawRegistrationKey != null) {
            return rawRegistrationKey;
        }
        VehicleRefDto vehicleRef = event == null ? null : event.vehicleRef();
        VehicleRegistrationRefDto registration = vehicleRef == null ? null : vehicleRef.vehicleRegistration();
        return registration != null && registration.hasValue() ? normalize(registration.stableKey()) : null;
    }

    public static String vehicleKey(EventHubEventDto event) {
        JsonNode raw = rawPayload(event);
        String rawVehicleVin = canonicalVehicleKey(text(raw, "vehicleVin"));
        if (rawVehicleVin != null) {
            return rawVehicleVin;
        }
        String rawVehicleKey = canonicalVehicleKey(text(raw, "vehicleKey"));
        if (rawVehicleKey != null) {
            return rawVehicleKey;
        }
        VehicleRefDto vehicleRef = event == null ? null : event.vehicleRef();
        return vehicleRef == null ? null : canonicalVehicleKey(vehicleRef.vin());
    }

    public static String requestDriverKey(
            UnifiedRuntimeProcessingRequest request,
            List<EventHubEventDto> events
    ) {
        if (request == null) {
            return firstEventDriverKey(events);
        }
        if (request.driverKey() != null) {
            return request.driverKey();
        }
        if (request.driverCardNation() != null && request.driverCardNumber() != null) {
            return request.driverCardNation() + ":" + request.driverCardNumber();
        }
        String eventDriverKey = firstEventDriverKey(events);
        if (eventDriverKey != null) {
            return eventDriverKey;
        }
        return request.driverCardNumber();
    }

    public static JsonNode rawPayload(EventHubEventDto event) {
        if (event == null || event.payload() == null || event.payload().isNull() || event.payload().isMissingNode()) {
            return null;
        }
        JsonNode raw = event.payload().get("raw");
        return raw == null || raw.isNull() ? event.payload() : raw;
    }

    public static String text(JsonNode node, String field) {
        if (node == null || field == null) {
            return null;
        }
        JsonNode value = node.get(field);
        if (value == null || value.isNull()) {
            return null;
        }
        String text = value.asText(null);
        return text == null || text.isBlank() ? null : text.trim();
    }

    private static String firstEventDriverKey(List<EventHubEventDto> events) {
        for (EventHubEventDto event : events == null ? List.<EventHubEventDto>of() : events) {
            String driverKey = driverKey(event);
            if (driverKey != null) {
                return driverKey;
            }
        }
        return null;
    }

    private static String canonicalVehicleKey(String value) {
        String normalized = normalize(value);
        if (normalized == null) {
            return null;
        }
        if (normalized.startsWith("VIN:")) {
            return normalize(normalized.substring("VIN:".length()));
        }
        if (normalized.startsWith("SOURCE_VEHICLE:")
                || normalized.startsWith("REG:")
                || normalized.startsWith("VR:")
                || normalized.contains("|")) {
            return null;
        }
        return normalized.toUpperCase();
    }

    private static String canonicalRegistrationKey(String value) {
        String normalized = normalize(value);
        if (normalized == null) {
            return null;
        }
        return normalized.startsWith("VR:") ? normalize(normalized.substring("VR:".length())) : normalized;
    }

    private static String firstNonBlank(String... values) {
        if (values == null) {
            return null;
        }
        for (String value : values) {
            String normalized = normalize(value);
            if (normalized != null) {
                return normalized;
            }
        }
        return null;
    }

    private static String normalize(String value) {
        return value == null || value.isBlank() ? null : value.trim();
    }
}
