package com.lingniu.ingest.protocol.jt808.model;

import java.time.Instant;
import java.util.List;
import java.util.Map;

/**
 * 已解析的消息体。sealed，新增消息体时必须同步新增子类型与 Parser。
 */
public sealed interface Jt808Body
        permits Jt808Body.Register, Jt808Body.Auth, Jt808Body.Location,
                Jt808Body.LocationBatch, Jt808Body.Unregister,
                Jt808Body.ParamsReport, Jt808Body.TerminalAttrs,
                Jt808Body.MediaEvent, Jt808Body.MediaUpload,
                Jt808Body.MediaAttributes, Jt808Body.FileUploadComplete,
                Jt808Body.FileList, Jt808Body.PassengerVolume,
                Jt808Body.Passthrough, Jt808Body.Heartbeat, Jt808Body.Raw,
                Jt808Body.Malformed {

    /** 终端注册 0x0100。 */
    record Register(
            int province,
            int city,
            String maker,
            String deviceType,
            String deviceId,
            int plateColor,
            String plate
    ) implements Jt808Body {}

    /** 终端鉴权 0x0102。 */
    record Auth(String token, String imei, String softwareVersion) implements Jt808Body {}

    /** 位置信息汇报 0x0200。 */
    record Location(
            long alarmFlag,
            long statusFlag,
            double longitude,
            double latitude,
            int altitudeM,
            double speedKmh,
            int directionDeg,
            Instant deviceTime,
            Map<Integer, byte[]> extensionItems
    ) implements Jt808Body {
        public Location(long alarmFlag,
                        long statusFlag,
                        double longitude,
                        double latitude,
                        int altitudeM,
                        double speedKmh,
                        int directionDeg,
                        Instant deviceTime) {
            this(alarmFlag, statusFlag, longitude, latitude, altitudeM, speedKmh,
                    directionDeg, deviceTime, Map.of());
        }

        public Location {
            extensionItems = extensionItems == null ? Map.of() : Map.copyOf(extensionItems);
        }
    }

    /** 位置信息批量上传 0x0704。 */
    record LocationBatch(
            int batchType,
            List<Location> locations
    ) implements Jt808Body {}

    /** 终端注销 0x0003。 */
    record Unregister() implements Jt808Body {}

    /** 查询终端参数应答 0x0104。 */
    record ParamsReport(
            int responseSerialNo,
            Map<Long, byte[]> parameters
    ) implements Jt808Body {}

    /** 查询终端属性应答 0x0107。 */
    record TerminalAttrs(
            int terminalType,
            String maker,
            String terminalModel,
            String terminalId,
            String iccid,
            String hardwareVersion,
            String firmwareVersion,
            int gnssProperty,
            int commProperty
    ) implements Jt808Body {}

    /** 多媒体事件信息上传 0x0800。 */
    record MediaEvent(
            long mediaId,
            int mediaType,
            int mediaFormat,
            int eventCode,
            int channelId
    ) implements Jt808Body {}

    /** 多媒体数据上传 0x0801。 */
    record MediaUpload(
            long mediaId,
            int mediaType,
            int mediaFormat,
            int eventCode,
            int channelId,
            Location location,
            byte[] data
    ) implements Jt808Body {}

    /** JT/T 1078 终端上传音视频属性 0x1003。 */
    record MediaAttributes(
            int inputAudioEncoding,
            int inputAudioChannels,
            int inputAudioSampleRate,
            int inputAudioBitDepth,
            int audioFrameLength,
            boolean audioOutputSupported,
            int videoEncoding,
            int maxAudioChannels,
            int maxVideoChannels,
            byte[] raw
    ) implements Jt808Body {}

    /** JT/T 1078 文件上传完成通知 0x1206。 */
    record FileUploadComplete(
            int responseSerialNo,
            int result,
            byte[] raw
    ) implements Jt808Body {}

    /** JT/T 1078 终端上传文件列表 0x1205。 */
    record FileList(
            int responseSerialNo,
            long fileCount,
            byte[] raw
    ) implements Jt808Body {}

    /** JT/T 1078 终端上传乘客流量 0x1005。 */
    record PassengerVolume(
            int channelId,
            String startTime,
            String endTime,
            int passengerGetOn,
            int passengerGetOff,
            byte[] raw
    ) implements Jt808Body {}

    /** 数据上行透传 0x0900。 */
    record Passthrough(
            int passthroughType,
            byte[] data
    ) implements Jt808Body {}

    /** 心跳 0x0002（无 body）。 */
    record Heartbeat() implements Jt808Body {}

    /** 未实现 Parser 的消息体，透传原始字节。 */
    record Raw(int messageId, byte[] bytes) implements Jt808Body {}

    /** 入站帧整体解析失败，保留原始字节便于冷存、查询和排障。 */
    record Malformed(byte[] bytes, String peer, String errorMessage) implements Jt808Body {}
}
