// Event routing and aggregation protocol (ADR-027)
// Defines PeatEvent, aggregation policies, and event summaries
// Version: 1.0.0

syntax = "proto3";

package cap.event.v1;

import "common.proto";

// Core event message for products, anomalies, telemetry, and commands
// Events flow upward through the hierarchy and are aggregated at echelon boundaries
message PeatEvent {
  // Unique event identifier (UUID)
  string event_id = 1;

  // When the event was generated
  cap.common.v1.Timestamp timestamp = 2;

  // Node that generated this event
  string source_node_id = 3;

  // Formation the source node belongs to
  string source_formation_id = 4;

  // Optional: specific software instance that generated the event
  optional string source_instance_id = 5;

  // Event classification
  EventClass event_class = 6;

  // Application-defined event type identifier (e.g., "detection", "telemetry", "anomaly")
  string event_type = 7;

  // Routing and aggregation policy
  AggregationPolicy routing = 8;

  // Application-defined payload (serialized as bytes for flexibility)
  // Use prost_types::Any semantics - type_url + value
  string payload_type_url = 10;
  bytes payload_value = 11;
}

// Event classification determines handling behavior
enum EventClass {
  EVENT_CLASS_UNSPECIFIED = 0;

  // Outputs from software (detections, decisions, classifications)
  EVENT_CLASS_PRODUCT = 1;

  // Anomalies requiring attention (unusual patterns, alerts)
  EVENT_CLASS_ANOMALY = 2;

  // Metrics, health, diagnostics
  EVENT_CLASS_TELEMETRY = 3;

  // Downward directives (commands flowing down hierarchy)
  EVENT_CLASS_COMMAND = 4;
}

// Aggregation and routing policy for events
message AggregationPolicy {
  // How this event should propagate through the hierarchy
  PropagationMode propagation = 1;

  // Priority for transmission scheduling
  EventPriority priority = 2;

  // Time-to-live in seconds (0 = no expiry)
  uint32 ttl_seconds = 3;

  // Aggregation window in milliseconds for SUMMARY mode
  // Events within this window are batched into a single summary
  uint32 aggregation_window_ms = 4;
}

// How events propagate through the hierarchy
enum PropagationMode {
  // Forward complete event upward immediately
  PROPAGATION_FULL = 0;

  // Aggregate events at each echelon, forward summaries
  PROPAGATION_SUMMARY = 1;

  // Store locally, respond to queries from higher echelons
  PROPAGATION_QUERY = 2;

  // No propagation, local storage only
  PROPAGATION_LOCAL = 3;
}

// Event priority for transmission scheduling
// CRITICAL events preempt all other traffic
enum EventPriority {
  // Immediate transmission, preempts other traffic
  PRIORITY_CRITICAL = 0;

  // High priority, after CRITICAL
  PRIORITY_HIGH = 1;

  // Normal priority (default)
  PRIORITY_NORMAL = 2;

  // Low priority, transmitted when bandwidth available
  PRIORITY_LOW = 3;
}

// Summary of aggregated events (generated by EchelonAggregator)
message EventSummary {
  // Formation that generated this summary
  string formation_id = 1;

  // Aggregation window timestamps
  cap.common.v1.Timestamp window_start = 2;
  cap.common.v1.Timestamp window_end = 3;

  // Event class and type being summarized
  EventClass event_class = 4;
  string event_type = 5;

  // Count of events in this summary
  uint32 event_count = 6;

  // Nodes that contributed events
  repeated string source_node_ids = 7;

  // Application-specific summary payload
  string summary_type_url = 10;
  bytes summary_value = 11;
}

// Wire protocol message for event transmission
message EventTransmission {
  oneof payload {
    // Single event
    PeatEvent event = 1;

    // Batch of events (efficiency optimization)
    EventBatch batch = 2;

    // Event query request
    EventQuery query = 3;

    // Query response
    EventQueryResponse query_response = 4;
  }
}

// Batch of events for efficient transmission
message EventBatch {
  repeated PeatEvent events = 1;
}

// Query for events stored at subordinate echelons
message EventQuery {
  // Query identifier for correlation
  string query_id = 1;

  // Node requesting the query
  string requester_id = 2;

  // Query scope
  QueryScope scope = 3;

  // Event filters
  EventFilters filters = 4;

  // Maximum events to return
  uint32 limit = 5;
}

// Query scope - what nodes to query
message QueryScope {
  oneof target {
    // Query specific node
    string node_id = 1;

    // Query entire formation
    string formation_id = 2;

    // Query all subordinates of requester
    bool subordinates = 3;
  }
}

// Filters for event queries
message EventFilters {
  // Filter by event class
  optional EventClass event_class = 1;

  // Filter by event type
  optional string event_type = 2;

  // Filter by time range (Unix timestamps)
  optional uint64 after_seconds = 3;
  optional uint64 before_seconds = 4;

  // Filter by source instance
  optional string source_instance_id = 5;
}

// Response to an event query
message EventQueryResponse {
  // Matching query ID
  string query_id = 1;

  // Node responding
  string responder_id = 2;

  // Matching events
  repeated PeatEvent events = 3;

  // Total matching events (may be > events.len() if limited)
  uint32 total_matching = 4;

  // Whether results were truncated due to limit
  bool truncated = 5;
}
