syntax = "proto3";

package worldmonitor.supply_chain.v1;

message ShippingRatePoint {
  string date = 1;
  double value = 2;
}

message ShippingIndex {
  string index_id = 1;
  string name = 2;
  double current_value = 3;
  double previous_value = 4;
  double change_pct = 5;
  string unit = 6;
  repeated ShippingRatePoint history = 7;
  bool spike_alert = 8;
}

message FlowEstimate {
  // Current estimated flow in million barrels/day. Computed as
  // baseline_mbd * flow_ratio.
  double current_mbd = 1;
  // EIA 2023 annual reference level in million barrels/day for the mapped
  // seven-item live-flow subset.
  double baseline_mbd = 2;
  // Latest 7-day PortWatch average divided by the preceding rolling baseline
  // window of up to 90 days, clamped to 0.0-1.5.
  double flow_ratio = 3;
  // True when each of the latest 3 daily ratios is below 85% of the same
  // rolling baseline window. Separate from the green/yellow/red status badge.
  bool disrupted = 4;
  // Flow source: "portwatch-dwt" when DWT-majority coverage is used,
  // otherwise "portwatch-counts" for vessel-count coverage.
  string source = 5;
  // Nearest active GDACS hazard alert level within the configured radius:
  // "RED", "ORANGE", or empty string when no nearby alert applies.
  string hazard_alert_level = 6;
  // Name of the nearest active GDACS hazard event within the configured
  // radius, or empty string when no nearby alert applies.
  string hazard_alert_name = 7;
}

/**
 * War risk tier derived from Lloyd's JWC Listed Areas + OSINT threat classification.
 * This is a FREE field (no PRO gate) — it exposes the existing server-internal
 * threatLevel from ChokepointConfig, making it available to clients for badges
 * and bypass corridor scoring.
 */
enum WarRiskTier {
  WAR_RISK_TIER_UNSPECIFIED = 0;
  WAR_RISK_TIER_NORMAL = 1;
  WAR_RISK_TIER_ELEVATED = 2;
  WAR_RISK_TIER_HIGH = 3;
  WAR_RISK_TIER_CRITICAL = 4;
  WAR_RISK_TIER_WAR_ZONE = 5;
}

message ChokepointInfo {
  string id = 1;
  string name = 2;
  double lat = 3;
  double lon = 4;
  int32 disruption_score = 5;
  // Traffic-light score badge: green (<20), yellow (20-49), or red (>=50).
  // Not an operational closure taxonomy.
  string status = 6;
  int32 active_warnings = 7;
  string congestion_level = 8;
  repeated string affected_routes = 9;
  string description = 10;
  int32 ais_disruptions = 11;
  repeated string directions = 12;
  repeated DirectionalDwt directional_dwt = 13 [deprecated = true];
  TransitSummary transit_summary = 14;
  FlowEstimate flow_estimate = 15;
  WarRiskTier war_risk_tier = 16;
}

message DirectionalDwt {
  string direction = 1;
  double dwt_thousand_tonnes = 2;
  double wow_change_pct = 3;
}

message TransitDayCount {
  string date = 1;
  int32 tanker = 2;
  int32 cargo = 3;
  int32 other = 4;
  int32 total = 5;
  int32 container = 6;
  int32 dry_bulk = 7;
  int32 general_cargo = 8;
  int32 roro = 9;
  double cap_container = 10;
  double cap_dry_bulk = 11;
  double cap_general_cargo = 12;
  double cap_roro = 13;
  double cap_tanker = 14;
}

message TransitSummary {
  int32 today_total = 1;
  int32 today_tanker = 2;
  int32 today_cargo = 3;
  int32 today_other = 4;
  double wow_change_pct = 5;
  repeated TransitDayCount history = 6;
  string risk_level = 7;
  int32 incident_count_7d = 8;
  double disruption_pct = 9;
  string risk_summary = 10;
  string risk_report_action = 11;
  // False when the upstream portwatch/relay source did not return data for
  // this chokepoint in the current cycle — the summary fields are zero-state
  // fill, not a genuine "zero traffic" reading. Client should render a
  // "transit data unavailable" indicator and skip stat/chart rendering.
  bool data_available = 12;
}

message MineralProducer {
  string country = 1;
  string country_code = 2;
  double production_tonnes = 3;
  double share_pct = 4;
}

message CriticalMineral {
  string mineral = 1;
  repeated MineralProducer top_producers = 2;
  double hhi = 3;
  string risk_rating = 4;
  double global_production = 5;
  string unit = 6;
}
