//! Cross-component traits.
//!
//! These traits let one component push into another's transport without
//! importing the receiving crate. The composition root in
//! `crates/autopilot/src/runtime.rs` wires concrete implementations.

use async_trait::async_trait;

use crate::error::Result;
use crate::models::detection::DetectionBatch;
use crate::models::frame::Frame;
use crate::models::operator::OperatorCommand;
use crate::models::vlm::VlmAssessment;

/// Telemetry uplink. Implemented by `telemetry_stream`, consumed by
/// `operator_bridge` (for overlay/POI surfacing) and `mavlink_layer` (for
/// piggybacked flight telemetry).
#[async_trait]
pub trait TelemetrySink: Send + Sync {
    async fn push_frame(&self, frame: Frame) -> Result<()>;
    async fn push_detections(&self, batch: DetectionBatch) -> Result<()>;
}

/// MAVLink command surface. Implemented by `mavlink_layer`, consumed by
/// `mission_executor` and other components that need to emit MAVLink commands.
#[async_trait]
pub trait MavlinkSink: Send + Sync {
    async fn send_raw(&self, msg: Vec<u8>) -> Result<()>;
}

/// Tier-3 visual-language-model provider. Default impl in `vlm_client` returns
/// `VlmAssessment { status: Disabled, label: Inconclusive, ... }` when the
/// `vlm` feature is off, satisfying the optionality contract.
#[async_trait]
pub trait VlmProvider: Send + Sync {
    async fn assess(&self, roi: Vec<u8>, prompt: String) -> Result<VlmAssessment>;
}

/// Operator-command dispatch. Implemented by `operator_bridge`, fed by the
/// composition root from `telemetry_stream`'s downlink.
#[async_trait]
pub trait OperatorCommandSink: Send + Sync {
    async fn dispatch(&self, command: OperatorCommand) -> Result<()>;
}
