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

import com.lingniu.ingest.api.ProtocolId;
import com.lingniu.ingest.api.annotation.EventEmit;
import com.lingniu.ingest.api.annotation.MessageMapping;
import com.lingniu.ingest.api.annotation.ProtocolHandler;
import com.lingniu.ingest.api.event.VehicleEvent;
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 com.lingniu.ingest.protocol.jt1078.media.Jt1078MalformedRtpPacket;
import com.lingniu.ingest.protocol.jt1078.media.Jt1078MediaMessageId;

import java.time.Instant;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.UUID;

@ProtocolHandler(protocol = ProtocolId.JT1078)
public final class Jt1078MalformedRtpHandler {

    private final VehicleIdentityResolver identityResolver;

    public Jt1078MalformedRtpHandler(VehicleIdentityResolver identityResolver) {
        this.identityResolver = Objects.requireNonNull(identityResolver, "identityResolver must not be null");
    }

    @MessageMapping(command = Jt1078MediaMessageId.MALFORMED_RTP, desc = "JT1078 RTP 入口坏包兜底")
    @EventEmit(VehicleEvent.Passthrough.class)
    public List<VehicleEvent> onMalformedRtp(Jt1078MalformedRtpPacket malformed) {
        if (malformed == null) {
            return List.of();
        }
        Instant eventTime = 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("vin", identity.identity().vin());
        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()));
        return List.of(new VehicleEvent.Passthrough(
                UUID.randomUUID().toString(),
                identity.identity().vin(),
                ProtocolId.JT1078,
                eventTime,
                Instant.now(),
                null,
                Map.copyOf(metadata),
                Jt1078MediaMessageId.MALFORMED_RTP,
                malformed.rawBytes() == null ? new byte[0] : malformed.rawBytes()));
    }

    private IdentityResolution resolveIdentity(Jt1078MalformedRtpPacket malformed) {
        try {
            return new IdentityResolution(identityResolver.resolve(new VehicleIdentityLookup(
                    ProtocolId.JT1078, "", safe(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) {
    }
}
