// 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::client::FromCharacteristic;
use bt_gatt::client::PeerService;
use bt_gatt::client::PeerServiceHandle;
use bt_gatt::Client;
use bt_gatt::GattTypes;

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

/// Represents a connection to a single peer and manages its audio streams.
pub struct BapUnicastClient<T: GattTypes> {
    peer_id: PeerId,
    #[allow(unused)]
    gatt_client: T::Client,
    // TODO: Add ASCS and PACS clients here.
}

impl<T: GattTypes> BapUnicastClient<T> {
    pub fn new(peer_id: PeerId, gatt_client: T::Client) -> Self {
        Self { peer_id, gatt_client }
    }

    pub fn peer_id(&self) -> PeerId {
        self.peer_id
    }

    /// Discovers PACS and ASCS and returns supported configurations.
    pub async fn discover(&mut self) -> Result<SupportedCapabilities, Error>
    where
        <T as GattTypes>::NotificationStream: Send,
    {
        // 1. Discover PACS and read capabilities.
        let pacs_handles = self.gatt_client.find_service(bt_pacs::PACS_UUID).await?;

        if pacs_handles.len() != 1 {
            return Err(Error::Configuration(format!(
                "{} PACS service(s) - not unique",
                pacs_handles.len()
            )));
        }

        let handle = &pacs_handles[0];
        let mut pac_records = vec![];

        let service = handle.connect().await?;

        let chrs = service.discover_characteristics(None).await?;

        for chr in chrs {
            if chr.uuid == bt_pacs::SourcePac::UUID {
                let source_pac = bt_pacs::SourcePac::try_read::<T>(chr, &service).await?;
                pac_records.extend(source_pac.capabilities);
            } else if chr.uuid == bt_pacs::SinkPac::UUID {
                let sink_pac = bt_pacs::SinkPac::try_read::<T>(chr, &service).await?;
                pac_records.extend(sink_pac.capabilities);
            }
        }

        // 2. Discover ASCS and count endpoints.
        let ascs_handles = self.gatt_client.find_service(bt_ascs::server::ASCS_UUID).await?;

        if ascs_handles.len() != 1 {
            return Err(Error::Configuration(format!(
                "{} ASCS service(s) - not unique",
                ascs_handles.len()
            )));
        }

        let handle = &ascs_handles[0];

        let mut sink_ase_count = 0;
        let mut source_ase_count = 0;

        let service = handle.connect().await?;

        let ascs_client =
            bt_ascs::client::AudioStreamControlServiceClient::<T>::create(service).await?;

        sink_ase_count += ascs_client.endpoints.sink_ases().len();
        source_ase_count += ascs_client.endpoints.source_ases().len();

        Ok(crate::mapping::map_capabilities(&pac_records, sink_ase_count, source_ase_count))
    }
}

#[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_discover_success() {
        let mut client = FakeClient::new();
        let _pacs_service = setup_pacs_service(&mut client);
        let _ascs_service = setup_ascs_service(&mut client, 1, 1);

        let mut unicast_client = BapUnicastClient::<FakeTypes>::new(PeerId(1), client);
        let mapping = futures::executor::block_on(unicast_client.discover())
            .expect("discovery should succeed");
        assert!(mapping.contains_key(&Configuration::MonoAudioSink));
        assert!(mapping.contains_key(&Configuration::Conversational));
    }

    #[test]
    fn test_discover_no_services() {
        let client = FakeClient::new();

        let mut unicast_client = BapUnicastClient::<FakeTypes>::new(PeerId(1), client);
        let result = futures::executor::block_on(unicast_client.discover());
        assert!(matches!(result, Err(Error::Configuration(_))));
    }

    #[test]
    fn test_discover_no_pacs_service() {
        let mut client = FakeClient::new();
        let _ascs_service = setup_ascs_service(&mut client, 1, 1);

        let mut unicast_client = BapUnicastClient::<FakeTypes>::new(PeerId(1), client);
        let result = futures::executor::block_on(unicast_client.discover());
        assert!(matches!(result, Err(Error::Configuration(_))));
    }

    #[test]
    fn test_discover_multiple_pacs_services() {
        let mut client = FakeClient::new();
        let _pacs_service1 = setup_pacs_service(&mut client);
        let _pacs_service2 = setup_pacs_service(&mut client);
        let _ascs_service = setup_ascs_service(&mut client, 1, 1);

        let mut unicast_client = BapUnicastClient::<FakeTypes>::new(PeerId(1), client);
        let result = futures::executor::block_on(unicast_client.discover());
        assert!(matches!(result, Err(Error::Configuration(_))));
    }

    #[test]
    fn test_discover_no_ascs_service() {
        let mut client = FakeClient::new();
        let _pacs_service = setup_pacs_service(&mut client);

        let mut unicast_client = BapUnicastClient::<FakeTypes>::new(PeerId(1), client);
        let result = futures::executor::block_on(unicast_client.discover());
        assert!(matches!(result, Err(Error::Configuration(_))));
    }

    #[test]
    fn test_discover_multiple_ascs_services() {
        let mut client = FakeClient::new();
        let _pacs_service = setup_pacs_service(&mut client);
        let _ascs_service1 = setup_ascs_service(&mut client, 1, 1);
        let _ascs_service2 = setup_ascs_service(&mut client, 1, 1);

        let mut unicast_client = BapUnicastClient::<FakeTypes>::new(PeerId(1), client);
        let result = futures::executor::block_on(unicast_client.discover());
        assert!(matches!(result, Err(Error::Configuration(_))));
    }
}
