// Copyright 2026 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

use crate::client::BapUnicastClient;
use crate::types::Error;
use bt_common::PeerId;
use std::collections::HashMap;

/// Manages multiple BAP Unicast peers.
#[derive(Debug, Default)]
pub struct BapUnicastManager {
    peers: HashMap<PeerId, BapUnicastClient>,
}

impl BapUnicastManager {
    pub fn new() -> Self {
        Self::default()
    }

    /// Add a peer to the manager.
    /// In the future, this will trigger discovery.
    pub async fn add_peer(&mut self, peer_id: PeerId) -> Result<(), Error> {
        if self.peers.contains_key(&peer_id) {
            return Err(Error::PeerAlreadyExists(peer_id));
        }

        let client = BapUnicastClient::new(peer_id);
        self.peers.insert(peer_id, client);
        Ok(())
    }

    /// Remove a peer from the manager.
    pub fn remove_peer(&mut self, peer_id: PeerId) -> Result<(), Error> {
        if self.peers.remove(&peer_id).is_none() {
            return Err(Error::PeerNotFound(peer_id));
        }
        Ok(())
    }
}

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

    #[test]
    fn test_add_remove_peer() {
        let mut manager = BapUnicastManager::new();
        let peer_id = PeerId(1);

        assert!(futures::executor::block_on(manager.add_peer(peer_id)).is_ok());
        assert!(futures::executor::block_on(manager.add_peer(peer_id)).is_err()); // Duplicate

        assert!(manager.remove_peer(peer_id).is_ok());
        assert!(manager.remove_peer(peer_id).is_err()); // Not found
    }
}
