// 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 bt_common::PeerId;
use bt_gatt::GattTypes;
use std::collections::HashMap;

use crate::client::BapUnicastClient;
use crate::types::{Error, SupportedCapabilities};

/// Manages multiple BAP Unicast peers.
pub struct BapUnicastManager<T: GattTypes> {
    peers: HashMap<PeerId, BapUnicastClient<T>>,
}

impl<T: GattTypes> BapUnicastManager<T> {
    pub fn new() -> Self {
        Self { peers: HashMap::new() }
    }

    /// Add a peer to the manager.
    /// Triggers the connection and discovery of PACS and ASCS on the remote
    /// peer.
    pub async fn add_peer(
        &mut self,
        peer_id: PeerId,
        gatt_client: T::Client,
    ) -> Result<SupportedCapabilities, Error>
    where
        <T as GattTypes>::NotificationStream: Send,
    {
        if self.peers.contains_key(&peer_id) {
            return Err(Error::PeerAlreadyExists(peer_id));
        }

        let mut client = BapUnicastClient::new(peer_id, gatt_client);
        let mapping = client.discover().await?;
        self.peers.insert(peer_id, client);
        Ok(mapping)
    }

    /// 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 crate::test_utils::{setup_ascs_service, setup_pacs_service};
    use crate::Configuration;
    use bt_common::PeerId;
    use bt_gatt::test_utils::{FakeClient, FakeTypes};

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

        // 1. Setup PACS
        let _pacs_service = setup_pacs_service(&mut client);

        // 2. Setup ASCS
        let _ascs_service = setup_ascs_service(&mut client, 1, 1);

        let mapping =
            futures::executor::block_on(manager.add_peer(peer_id, client.clone())).unwrap();
        assert!(mapping.contains_key(&Configuration::MonoAudioSink));
        assert!(mapping.contains_key(&Configuration::Conversational));

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

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

    #[test]
    fn test_add_peer_fails_non_unique_services() {
        let mut manager = BapUnicastManager::<FakeTypes>::new();
        let peer_id = PeerId(1);

        // 0 PACS services: add_peer fails and peer is not stored.
        let mut client = FakeClient::new();
        let _ascs_service = setup_ascs_service(&mut client, 1, 1);
        assert!(futures::executor::block_on(manager.add_peer(peer_id, client.clone())).is_err());
        assert!(manager.remove_peer(peer_id).is_err());

        // Multiple PACS services: add_peer fails and peer is not stored.
        let mut client = FakeClient::new();
        let _pacs1 = setup_pacs_service(&mut client);
        let _pacs2 = setup_pacs_service(&mut client);
        let _ascs = setup_ascs_service(&mut client, 1, 1);
        assert!(futures::executor::block_on(manager.add_peer(peer_id, client.clone())).is_err());
        assert!(manager.remove_peer(peer_id).is_err());

        // 0 ASCS services: add_peer fails and peer is not stored.
        let mut client = FakeClient::new();
        let _pacs = setup_pacs_service(&mut client);
        assert!(futures::executor::block_on(manager.add_peer(peer_id, client.clone())).is_err());
        assert!(manager.remove_peer(peer_id).is_err());

        // Multiple ASCS services: add_peer fails and peer is not stored.
        let mut client = FakeClient::new();
        let _pacs = setup_pacs_service(&mut client);
        let _ascs1 = setup_ascs_service(&mut client, 1, 1);
        let _ascs2 = setup_ascs_service(&mut client, 1, 1);
        assert!(futures::executor::block_on(manager.add_peer(peer_id, client.clone())).is_err());
        assert!(manager.remove_peer(peer_id).is_err());
    }
}
