syntax = "proto3";

package com.lingniu.ingest.sink.kafka.proto;

option java_multiple_files = true;
option java_package = "com.lingniu.ingest.sink.kafka.proto";
option java_outer_classname = "VehicleEnvelopeProto";

// 统一消息外壳：所有 Topic 共用此 Envelope，payload 通过 oneof 区分具体事件类型。
message VehicleEnvelope {
  string schema_version = 1;
  string event_id       = 2;
  string trace_id       = 3;
  string vin            = 4;
  string source         = 5;   // ProtocolId 字符串形式
  string protocol_version = 6;
  int64  event_time_ms  = 7;
  int64  ingest_time_ms = 8;
  string ingest_node_id = 9;
  map<string, string> metadata = 10;

  oneof payload {
    RealtimePayload  realtime  = 20;
    LocationPayload  location  = 21;
    AlarmPayload     alarm     = 22;
    LoginPayload     login     = 23;
    LogoutPayload    logout    = 24;
    HeartbeatPayload heartbeat = 25;
    MediaMetaPayload media_meta = 26;
    PassthroughPayload passthrough = 27;
  }

  // 可选：原始字节指针
  RawArchiveRef raw_archive = 40;

  // 全字段内部遥测快照。新下游消费者优先读取这里，避免依赖协议字段名。
  TelemetrySnapshot telemetry_snapshot = 50;

  // 新一代事实模型：RAW 帧索引与解析事实，均不携带完整 raw bytes。
  RawFrameFactPayload raw_frame_fact = 60;
  DecodedFactPayload decoded_fact = 61;
}

message RawArchiveRef {
  string uri      = 1;
  string checksum = 2;
  int64  size_bytes = 3;
  string parsed_json = 4;
}

message TelemetrySnapshot {
  string event_type      = 1;
  string raw_archive_uri = 2;
  repeated TelemetryField fields = 3;
}

message TelemetryField {
  string key         = 1;
  string value_type  = 2;
  string value       = 3;
  string unit        = 4;
  string quality     = 5;
  string source_path = 6;
}

enum ParseStatusProto {
  PARSE_STATUS_UNSPECIFIED = 0;
  PARSE_STATUS_NOT_PARSED = 1;
  PARSE_STATUS_SUCCEEDED = 2;
  PARSE_STATUS_FAILED = 3;
}

message RawFrameFactPayload {
  string frame_id = 1;
  string vehicle_key = 2;
  string vin = 3;
  string phone = 4;
  int32 message_id = 5;
  int32 sub_type = 6;
  string raw_uri = 7;
  string checksum = 8;
  int64 raw_size_bytes = 9;
  ParseStatusProto parse_status = 10;
  string parse_error = 11;
  string peer = 12;
  map<string, string> metadata = 13;
}

message DecodedFactPayload {
  string fact_id = 1;
  string frame_id = 2;
  string fact_type = 3;
  string vehicle_key = 4;
  string vin = 5;
  string phone = 6;
  string raw_uri = 7;
  map<string, string> fields = 8;
  map<string, string> metadata = 9;
}

message RealtimePayload {
  optional double speed_kmh             = 1;
  optional double total_mileage_km      = 2;
  optional double battery_soc           = 3;
  optional double battery_voltage_v     = 4;
  optional double battery_current_a     = 5;
  optional double fc_voltage_v          = 6;
  optional double fc_current_a          = 7;
  optional double fc_temp_c             = 8;
  optional double hydrogen_remaining_kg = 9;
  optional double hydrogen_high_pressure_mpa = 10;
  optional double hydrogen_low_pressure_mpa  = 11;
  optional string vehicle_state         = 12;
  optional string charging_state        = 13;
  optional string running_mode          = 14;
  optional int32  gear_level            = 15;
  optional double accelerator_pedal     = 16;
  optional double brake_pedal           = 17;
  optional double longitude             = 18;
  optional double latitude              = 19;
  optional double altitude_m            = 20;
  optional double direction_deg         = 21;
  optional double ambient_temp_c        = 22;
  optional double coolant_temp_c        = 23;
}

message LocationPayload {
  double longitude    = 1;
  double latitude     = 2;
  double altitude_m   = 3;
  double speed_kmh    = 4;
  double direction_deg = 5;
  int64  alarm_flag   = 6;
  int64  status_flag  = 7;
}

message AlarmPayload {
  string   level           = 1;
  int32    alarm_type_code = 2;
  string   alarm_type_name = 3;
  repeated string fault_codes = 4;
  optional double longitude = 5;
  optional double latitude  = 6;
  // 通用报警标志位（2016 版 0~15 / 2025 版 0~27），对照 GB/T 32960.3 表 24。
  // 例：SOC_LOW / BATTERY_HIGH_TEMP / HYDROGEN_LEAK
  repeated string active_bits = 7;
}

message LoginPayload {
  string iccid             = 1;
  string protocol_version  = 2;
}

message LogoutPayload {}

message HeartbeatPayload {}

message MediaMetaPayload {
  string media_id     = 1;
  string media_type   = 2;
  int64  size_bytes   = 3;
  string archive_ref  = 4;
}

message PassthroughPayload {
  int32 passthrough_type = 1;
  bytes data             = 2;
}
