//! `operator_bridge` — POI surfacing + operator command authentication.
//!
//! Real implementation lands in:
//! - AZ-678 `operator_bridge_command_auth`
//! - AZ-679 `operator_bridge_poi_surface`
//! - AZ-680 `operator_bridge_command_dispatch`
//! - AZ-681 `operator_bridge_safety_and_bit_ack`

use async_trait::async_trait;
use serde::{Deserialize, Serialize};
use tokio::sync::mpsc;

use shared::contracts::OperatorCommandSink;
use shared::error::{AutopilotError, Result};
use shared::health::ComponentHealth;
use shared::models::mission::Coordinate;
use shared::models::operator::OperatorCommand;
use shared::models::poi::Poi;

const NAME: &str = "operator_bridge";

#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum OperatorDecision {
    Confirmed,
    Declined,
    TimedOut,
    StartTargetFollow,
    ReleaseTargetFollow,
}

#[derive(Debug, Clone)]
pub struct MiddleWaypointHint {
    pub mission_id: String,
    pub at: Coordinate,
}

#[derive(Debug, Clone)]
pub enum TargetFollowEvent {
    Start { target_id: String },
    Release,
}

pub struct OperatorBridge {
    middle_waypoint_tx: mpsc::Sender<MiddleWaypointHint>,
    target_follow_tx: mpsc::Sender<TargetFollowEvent>,
    middle_waypoint_rx: Option<mpsc::Receiver<MiddleWaypointHint>>,
    target_follow_rx: Option<mpsc::Receiver<TargetFollowEvent>>,
}

impl OperatorBridge {
    pub fn new(channel_capacity: usize) -> Self {
        let (mw_tx, mw_rx) = mpsc::channel(channel_capacity);
        let (tf_tx, tf_rx) = mpsc::channel(channel_capacity);
        Self {
            middle_waypoint_tx: mw_tx,
            target_follow_tx: tf_tx,
            middle_waypoint_rx: Some(mw_rx),
            target_follow_rx: Some(tf_rx),
        }
    }

    pub fn handle(&self) -> OperatorBridgeHandle {
        OperatorBridgeHandle {
            middle_waypoint_tx: self.middle_waypoint_tx.clone(),
            target_follow_tx: self.target_follow_tx.clone(),
        }
    }

    pub fn take_middle_waypoint_receiver(&mut self) -> Option<mpsc::Receiver<MiddleWaypointHint>> {
        self.middle_waypoint_rx.take()
    }

    pub fn take_target_follow_receiver(&mut self) -> Option<mpsc::Receiver<TargetFollowEvent>> {
        self.target_follow_rx.take()
    }
}

#[derive(Clone)]
pub struct OperatorBridgeHandle {
    #[allow(dead_code)]
    middle_waypoint_tx: mpsc::Sender<MiddleWaypointHint>,
    #[allow(dead_code)]
    target_follow_tx: mpsc::Sender<TargetFollowEvent>,
}

impl OperatorBridgeHandle {
    pub async fn surface_poi(&self, _poi: Poi) -> Result<OperatorDecision> {
        Err(AutopilotError::NotImplemented(
            "operator_bridge::surface_poi (AZ-679)",
        ))
    }

    pub fn health(&self) -> ComponentHealth {
        ComponentHealth::disabled(NAME)
    }
}

#[async_trait]
impl OperatorCommandSink for OperatorBridgeHandle {
    async fn dispatch(&self, _command: OperatorCommand) -> Result<()> {
        Err(AutopilotError::NotImplemented(
            "operator_bridge::dispatch (AZ-680)",
        ))
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn it_compiles() {
        let h = OperatorBridge::new(8).handle();
        assert_eq!(h.health().level, shared::health::HealthLevel::Disabled);
    }
}
