package com.lingniu.ingest.protocol.jt1078.media;

import com.lingniu.ingest.api.ProtocolId;
import com.lingniu.ingest.api.pipeline.RawFrame;
import com.lingniu.ingest.identity.VehicleIdentity;
import com.lingniu.ingest.identity.VehicleIdentityLookup;
import com.lingniu.ingest.identity.VehicleIdentityResolver;
import com.lingniu.ingest.identity.VehicleIdentitySource;

import java.time.Instant;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.function.Consumer;

public final class Jt1078MalformedRtpEventPublisher {

    private final VehicleIdentityResolver identityResolver;
    private final Consumer<RawFrame> dispatcher;

    public Jt1078MalformedRtpEventPublisher(VehicleIdentityResolver identityResolver,
                                            Consumer<RawFrame> dispatcher) {
        this.identityResolver = Objects.requireNonNull(identityResolver, "identityResolver must not be null");
        this.dispatcher = Objects.requireNonNull(dispatcher, "dispatcher must not be null");
    }

    public void publish(Jt1078MalformedRtpPacket malformed) {
        if (malformed == null) {
            return;
        }
        Instant now = malformed.receivedAt() == null ? Instant.now() : malformed.receivedAt();
        IdentityResolution identity = resolveIdentity(malformed);
        Map<String, String> metadata = new HashMap<>();
        metadata.put("transport", safe(malformed.transport()));
        metadata.put("peer", safe(malformed.peer()));
        metadata.put("sim", safe(malformed.sim()));
        metadata.put("identityResolved", Boolean.toString(identity.identity().resolved()));
        metadata.put("identitySource", identity.identity().source().name());
        if (identity.errorMessage() != null) {
            metadata.put("identityError", "true");
            metadata.put("identityErrorMessage", identity.errorMessage());
        }
        metadata.put("malformedRtp", "true");
        metadata.put("parseError", "true");
        metadata.put("parseErrorMessage", safe(malformed.reason()));
        metadata.put("packetLength", Integer.toString(malformed.packetLength()));
        metadata.put("reason", safe(malformed.reason()));
        metadata.put("vin", identity.identity().vin());
        dispatcher.accept(new RawFrame(
                ProtocolId.JT1078,
                Jt1078MediaMessageId.MALFORMED_RTP,
                0,
                malformed,
                malformed.rawBytes() == null ? new byte[0] : malformed.rawBytes(),
                Map.copyOf(metadata),
                now
                ));
    }

    private IdentityResolution resolveIdentity(Jt1078MalformedRtpPacket malformed) {
        try {
            return new IdentityResolution(identityResolver.resolve(new VehicleIdentityLookup(
                    ProtocolId.JT1078, "", malformed.sim(), "", "")), null);
        } catch (RuntimeException e) {
            return new IdentityResolution(
                    new VehicleIdentity("unknown", false, VehicleIdentitySource.UNKNOWN),
                    e.getMessage() == null ? "" : e.getMessage());
        }
    }

    private static String safe(String value) {
        return value == null ? "" : value;
    }

    private record IdentityResolution(VehicleIdentity identity, String errorMessage) {}
}
