// 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 futures::stream::{BoxStream, FuturesUnordered, StreamExt};
use std::collections::{HashMap, HashSet};

use bt_common::packet_encoding::Decodable;
use bt_common::Uuid;
use bt_gatt::client::{CharacteristicNotification, PeerService, ServiceCharacteristic};
use bt_gatt::connected_isochronous::{CigId, CisId, SduInterval};
use bt_gatt::types::Handle;

use crate::types::*;

/// 16-bit UUID value for the characteristics offered by the Audio
/// Stream Control Service.
pub const ASE_CONTROL_POINT_UUID: Uuid = Uuid::from_u16(0x2BC6);
pub const SINK_ASE_UUID: Uuid = Uuid::from_u16(0x2BC4);
pub const SOURCE_ASE_UUID: Uuid = Uuid::from_u16(0x2BC5);

#[derive(Debug, thiserror::Error, PartialEq, Clone)]
pub enum ClientError {
    #[error("Remote server is missing control point characteristic")]
    MissingControlPointCharacteristic,
    #[error("Remote server should only have 1 control point characteristic")]
    ExtraControlPointCharacteristic,
    #[error("Remote server doesn't have any audio stream endpoints")]
    MissingAudioStreamEndpoints,
    #[error("Notification stream closed before receiving all responses")]
    NotificationStreamClosed,
    #[error(
        "ASE {ase_id:?} transitioned to unexpected state: expected {expected:?}, got {actual:?}"
    )]
    UnexpectedStateTransition { ase_id: AseId, expected: AseState, actual: AseState },
    #[error("Unknown ASE ID: {0:?}")]
    UnknownAseId(AseId),
    #[error("ASE {ase_id:?} is in invalid starting state {actual:?} for opcode {opcode:?}")]
    InvalidStartState { ase_id: AseId, opcode: AseControlPointOpcode, actual: AseState },
    #[error("Remote server rejected operation: {0:?}")]
    RejectedOperation(Vec<ResponseCode>),
    #[error("ASE {ase_id:?} has invalid direction {direction:?} for opcode {opcode:?}")]
    InvalidDirection { ase_id: AseId, opcode: AseControlPointOpcode, direction: AudioDirection },
}

/// Represents a single source/sink ASE state characteristic.
pub struct ClientEndpoint {
    pub endpoint: AudioStreamEndpoint,
    pub notification_stream:
        BoxStream<'static, Result<CharacteristicNotification, bt_gatt::types::Error>>,
}

impl ClientEndpoint {
    pub async fn next_update(&mut self) -> Result<(AseId, AudioStreamEndpoint), Error> {
        let notification = self
            .notification_stream
            .next()
            .await
            .ok_or(Error::Client(ClientError::NotificationStreamClosed))??;
        let new_endpoint = AudioStreamEndpoint::from_char_value(
            self.endpoint.handle,
            self.endpoint.direction,
            &notification.value[..],
        )
        .map_err(|e| {
            bt_gatt::types::Error::Conversion(format!(
                "Failed to decode AudioStreamEndpoint: {:?}",
                e
            ))
        })?;
        Ok((self.endpoint.ase_id, new_endpoint))
    }
}

/// Represents a client request to configure QoS parameters on an ASE.
#[derive(Debug, Clone, PartialEq)]
pub enum QosConfigurationRequest {
    /// Completely custom QoS configuration parameters.
    Custom(QosConfiguration),

    /// Automatically derive constraint parameters (framing, PHYs,
    /// retransmissions, latency, presentation delay) from the server's
    /// published preferred parameters in the local cache, only requiring
    /// the host-allocated dynamic properties.
    Preferred {
        ase_id: AseId,
        cig_id: CigId,
        cis_id: CisId,
        sdu_interval: SduInterval,
        max_sdu: MaxSdu,
    },
}

impl QosConfigurationRequest {
    pub fn try_into_config<T: bt_gatt::GattTypes>(
        self,
        client: &AudioStreamControlServiceClient<T>,
    ) -> Result<QosConfiguration, Error> {
        match self {
            Self::Custom(c) => Ok(c),
            Self::Preferred { ase_id, cig_id, cis_id, sdu_interval, max_sdu } => {
                let endpoint = &client
                    .endpoints
                    .lookup_by_ase_id(ase_id)
                    .ok_or(Error::Client(ClientError::UnknownAseId(ase_id)))?
                    .endpoint;

                let params = endpoint.qos_parameters().ok_or(Error::Client(
                    ClientError::InvalidStartState {
                        ase_id,
                        opcode: AseControlPointOpcode::ConfigQos,
                        actual: endpoint.state,
                    },
                ))?;

                let presentation_delay = params.presentation_delay_range.min().clone();

                Ok(QosConfiguration {
                    ase_id,
                    cig_id,
                    cis_id,
                    sdu_interval,
                    framing: params.framing,
                    phy: params.preferred_phys.clone(),
                    max_sdu,
                    retransmission_number: params.preferred_retransmission_number,
                    max_transport_latency: params.max_transport_latency,
                    presentation_delay,
                })
            }
        }
    }
}

// See ASCS v1.0.1 4.2 for details.
pub struct AseControlPoint {
    pub handle: Handle,
    pub notification_stream:
        BoxStream<'static, Result<CharacteristicNotification, bt_gatt::types::Error>>,
}

/// Creates Audio Stream Control Service (ASCS) client instance
pub struct AudioStreamControlServiceClient<T: bt_gatt::GattTypes> {
    pub gatt_client: T::PeerService,
    pub control_point: AseControlPoint,
    pub endpoints: DiscoveredEndpoints,
}

pub struct DiscoveredEndpoints {
    pub sink: HashMap<Handle, ClientEndpoint>,
    pub source: HashMap<Handle, ClientEndpoint>,
}

impl DiscoveredEndpoints {
    /// Returns the ASE IDs of all discovered sink Audio Stream Endpoints.
    pub fn sink_ases(&self) -> Vec<AseId> {
        self.sink.values().map(|e| e.endpoint.ase_id).collect()
    }

    /// Returns the ASE IDs of all discovered source Audio Stream Endpoints.
    pub fn source_ases(&self) -> Vec<AseId> {
        self.source.values().map(|e| e.endpoint.ase_id).collect()
    }

    pub(crate) fn lookup_by_ase_id(&self, ase_id: AseId) -> Option<&ClientEndpoint> {
        if let Some(e) = self.sink.values().find(|e| e.endpoint.ase_id == ase_id) {
            return Some(e);
        }
        if let Some(e) = self.source.values().find(|e| e.endpoint.ase_id == ase_id) {
            return Some(e);
        }
        None
    }

    pub(crate) fn lookup_by_ase_id_mut(&mut self, ase_id: AseId) -> Option<&mut ClientEndpoint> {
        if let Some(e) = self.sink.values_mut().find(|e| e.endpoint.ase_id == ase_id) {
            return Some(e);
        }
        if let Some(e) = self.source.values_mut().find(|e| e.endpoint.ase_id == ase_id) {
            return Some(e);
        }
        None
    }
}

/// The outcome of an ASE control point operation, partitioning successfully
/// transitioned endpoints and failed response codes.
#[derive(Debug, Clone, PartialEq)]
pub struct AseControlOperationOutcome {
    accepted: HashMap<AseId, AudioStreamEndpoint>,
    rejected: HashMap<AseId, ResponseCode>,
}

impl AseControlOperationOutcome {
    pub(crate) fn new(
        accepted: HashMap<AseId, AudioStreamEndpoint>,
        rejected: HashMap<AseId, ResponseCode>,
    ) -> Self {
        Self { accepted, rejected }
    }

    /// Returns the map of successfully transitioned [`AudioStreamEndpoint`]s,
    /// keyed by their [`AseId`].
    pub fn accepted(&self) -> &HashMap<AseId, AudioStreamEndpoint> {
        &self.accepted
    }

    /// Returns the map of rejected [`ResponseCode`]s, keyed by their [`AseId`].
    pub fn rejected(&self) -> &HashMap<AseId, ResponseCode> {
        &self.rejected
    }
}

impl<T: bt_gatt::GattTypes> AudioStreamControlServiceClient<T> {
    pub async fn create(gatt_client: T::PeerService) -> Result<Self, Error>
    where
        <T as bt_gatt::GattTypes>::NotificationStream: std::marker::Send,
    {
        let control_point = Self::discover_control_point(&gatt_client).await?;
        let endpoints = Self::discover_all_endpoints(&gatt_client).await?;

        Ok(Self { gatt_client, control_point, endpoints })
    }

    async fn discover_control_point(gatt_client: &T::PeerService) -> Result<AseControlPoint, Error>
    where
        <T as bt_gatt::GattTypes>::NotificationStream: std::marker::Send,
    {
        let cp_chars = ServiceCharacteristic::<T>::find(gatt_client, ASE_CONTROL_POINT_UUID)
            .await
            .map_err(Error::Gatt)?;
        if cp_chars.is_empty() {
            return Err(ClientError::MissingControlPointCharacteristic.into());
        }
        if cp_chars.len() > 1 {
            return Err(ClientError::ExtraControlPointCharacteristic.into());
        }
        let cp_handle = *cp_chars[0].handle();
        let cp_stream = gatt_client.subscribe(&cp_handle);
        Ok(AseControlPoint { handle: cp_handle, notification_stream: cp_stream.boxed() })
    }

    async fn discover_all_endpoints(
        gatt_client: &T::PeerService,
    ) -> Result<DiscoveredEndpoints, Error>
    where
        <T as bt_gatt::GattTypes>::NotificationStream: std::marker::Send,
    {
        let sink_chars = ServiceCharacteristic::<T>::find(gatt_client, SINK_ASE_UUID)
            .await
            .map_err(Error::Gatt)?;

        let source_chars = ServiceCharacteristic::<T>::find(gatt_client, SOURCE_ASE_UUID)
            .await
            .map_err(Error::Gatt)?;

        if sink_chars.is_empty() && source_chars.is_empty() {
            return Err(ClientError::MissingAudioStreamEndpoints.into());
        }

        let mut sink_endpoints = HashMap::new();
        for c in sink_chars {
            let handle = *c.handle();
            let endpoint =
                Self::read_and_create_endpoint(gatt_client, handle, AudioDirection::Sink).await?;
            let notification_stream = gatt_client.subscribe(&handle).boxed();
            sink_endpoints.insert(handle, ClientEndpoint { endpoint, notification_stream });
        }

        let mut source_endpoints = HashMap::new();
        for c in source_chars {
            let handle = *c.handle();
            let endpoint =
                Self::read_and_create_endpoint(gatt_client, handle, AudioDirection::Source).await?;
            let notification_stream = gatt_client.subscribe(&handle).boxed();
            source_endpoints.insert(handle, ClientEndpoint { endpoint, notification_stream });
        }

        Ok(DiscoveredEndpoints { sink: sink_endpoints, source: source_endpoints })
    }

    /// Reads the current value of an ASE characteristic from the remote server
    /// and decodes it into an [`AudioStreamEndpoint`].
    async fn read_and_create_endpoint(
        gatt_client: &T::PeerService,
        handle: Handle,
        direction: AudioDirection,
    ) -> Result<AudioStreamEndpoint, Error> {
        let mut buf = vec![0; 255];
        let (read_bytes, _truncated) =
            gatt_client.read_characteristic(&handle, 0, &mut buf[..]).await.map_err(Error::Gatt)?;
        let endpoint = AudioStreamEndpoint::from_char_value(handle, direction, &buf[0..read_bytes])
            .map_err(|e| {
                bt_gatt::types::Error::Conversion(format!(
                    "Failed to decode AudioStreamEndpoint: {:?}",
                    e
                ))
            })?;
        Ok(endpoint)
    }

    /// Validates that the target ASE IDs are known to this client and that
    /// the requested `opcode` is allowed in their current state according
    /// to the ASCS state machine.
    ///
    /// Returns `Ok(())` if validation passes, or a `ClientError` (such as
    /// `UnknownAseId` or `InvalidStartState`) if any target ASE fails
    /// validation.
    fn validate_arguments<'a>(
        &self,
        opcode: AseControlPointOpcode,
        pending_ases: impl IntoIterator<Item = &'a AseId>,
    ) -> Result<(), Error> {
        for &ase_id in pending_ases {
            let endpoint = &self
                .endpoints
                .lookup_by_ase_id(ase_id)
                .ok_or(Error::Client(ClientError::UnknownAseId(ase_id)))?
                .endpoint;

            if !opcode.allowed_in_state(&endpoint.state) {
                return Err(Error::Client(ClientError::InvalidStartState {
                    ase_id,
                    opcode,
                    actual: endpoint.state,
                }));
            }
        }
        Ok(())
    }

    fn verify_ase_directions<'a>(
        &self,
        pending_ases: impl IntoIterator<Item = &'a AseId>,
        opcode: AseControlPointOpcode,
        expected: AudioDirection,
    ) -> Result<(), Error> {
        for &ase_id in pending_ases {
            let direction = self
                .endpoints
                .lookup_by_ase_id(ase_id)
                .ok_or(Error::Client(ClientError::UnknownAseId(ase_id)))?
                .endpoint
                .direction;
            if direction != expected {
                return Err(Error::Client(ClientError::InvalidDirection {
                    ase_id,
                    opcode,
                    direction,
                }));
            }
        }
        Ok(())
    }

    /// Encodes an ASE control operation and writes it to the ASE Control Point
    /// characteristic.
    async fn write_operation(&mut self, operation: &AseControlOperation) -> Result<(), Error> {
        use bt_common::packet_encoding::Encodable;

        let mut buf = vec![0; operation.encoded_len()];
        operation
            .encode(&mut buf[..])
            .map_err(|e| Error::Internal(format!("Failed to encode operation: {:?}", e)))?;

        self.gatt_client
            .write_characteristic(
                &self.control_point.handle,
                bt_gatt::types::WriteMode::WithoutResponse,
                0,
                &buf[..],
            )
            .await
            .map_err(Error::Gatt)
    }

    async fn collect_operation_responses(
        &mut self,
        operation: &AseControlOperation,
    ) -> Result<HashMap<AseId, ResponseCode>, Error> {
        let opcode = u8::try_from(operation)?;
        let mut remaining_ases: HashSet<AseId> = operation.ase_ids().copied().collect();
        let mut responses = HashMap::new();

        while !remaining_ases.is_empty() {
            let notification = self
                .control_point
                .notification_stream
                .next()
                .await
                .ok_or(Error::Client(ClientError::NotificationStreamClosed))?;
            let notification = notification.map_err(Error::from)?;

            let (cp_notification, _) = ControlPointNotification::decode(&notification.value[..]);
            let cp_notification = cp_notification.map_err(bt_gatt::types::Error::Encoding)?;
            if cp_notification.opcode != opcode {
                continue;
            }

            if cp_notification.number_of_ases == 0xFF {
                return Err(Error::Client(ClientError::RejectedOperation(
                    cp_notification.responses,
                )));
            }

            for r in cp_notification.responses {
                if remaining_ases.remove(&r.ase_id()) {
                    responses.insert(r.ase_id(), r);
                }
            }
        }

        Ok(responses)
    }

    async fn perform_and_verify_operation(
        &mut self,
        operation: AseControlOperation,
    ) -> Result<AseControlOperationOutcome, Error> {
        self.write_operation(&operation).await?;

        let responses = self.collect_operation_responses(&operation).await?;

        let mut successful_endpoints = HashMap::new();
        let opcode = AseControlPointOpcode::try_from(&operation).map_err(|e| {
            Error::Internal(format!("Failed to resolve opcode from operation: {:?}", e))
        })?;

        let (successful, failed_responses): (
            HashMap<AseId, ResponseCode>,
            HashMap<AseId, ResponseCode>,
        ) = responses.into_iter().partition(|(_, r)| r.is_success());

        let successful_ases: HashSet<AseId> = successful.keys().cloned().collect();

        if successful_ases.is_empty() {
            return Ok(AseControlOperationOutcome::new(HashMap::new(), failed_responses));
        }

        let updated_endpoints = {
            let mut notification_futures = FuturesUnordered::new();
            for endpoint in
                self.endpoints.sink.values_mut().chain(self.endpoints.source.values_mut())
            {
                if !successful_ases.contains(&endpoint.endpoint.ase_id) {
                    continue;
                }
                notification_futures.push(endpoint.next_update());
            }

            let mut updated_endpoints = Vec::with_capacity(successful_ases.len());
            while let Some(res) = notification_futures.next().await {
                updated_endpoints.push(res?);
            }
            updated_endpoints
        };

        for (ase_id, endpoint) in &updated_endpoints {
            if let Some(client_endpoint) = self.endpoints.lookup_by_ase_id_mut(*ase_id) {
                client_endpoint.endpoint = endpoint.clone();
            }
        }

        for (ase_id, endpoint) in updated_endpoints {
            if !opcode.allows_transition_to(endpoint.direction, &endpoint.state) {
                let expected = opcode.operation_target_states(endpoint.direction)[0];
                return Err(Error::Client(ClientError::UnexpectedStateTransition {
                    ase_id: endpoint.ase_id,
                    expected,
                    actual: endpoint.state,
                }));
            }
            successful_endpoints.insert(ase_id, endpoint);
        }

        Ok(AseControlOperationOutcome::new(successful_endpoints, failed_responses))
    }

    /// Performs the Configure Codec operation on one or more ASEs.
    ///
    /// # Arguments
    /// * `codec_configurations` - A vector of `CodecConfiguration` structs
    ///   containing the parameters for each ASE to be configured.
    ///
    /// # Returns
    /// On success, returns an [`AseControlOperationOutcome`] containing the
    /// results of the operation.
    pub async fn configure_codec(
        &mut self,
        codec_configurations: Vec<CodecConfiguration>,
    ) -> Result<AseControlOperationOutcome, Error> {
        self.validate_arguments(
            AseControlPointOpcode::ConfigCodec,
            codec_configurations.iter().map(|c| &c.ase_id),
        )?;

        let op = AseControlOperation::ConfigCodec { codec_configurations, responses: vec![] };

        self.perform_and_verify_operation(op).await
    }

    /// Performs the Configure QoS operation on one or more ASEs.
    ///
    /// # Arguments
    /// * `requests` - A vector of `QosConfigurationRequest` enums specifying
    ///   either custom or server-preferred configurations for each ASE.
    ///
    /// # Returns
    /// On success, returns an [`AseControlOperationOutcome`] containing the
    /// results of the operation.
    pub async fn configure_qos(
        &mut self,
        requests: Vec<QosConfigurationRequest>,
    ) -> Result<AseControlOperationOutcome, Error> {
        let qos_configurations: Vec<QosConfiguration> = requests
            .into_iter()
            .map(|req| req.try_into_config(self))
            .collect::<Result<Vec<_>, Error>>()?;

        self.validate_arguments(
            AseControlPointOpcode::ConfigQos,
            qos_configurations.iter().map(|q| &q.ase_id),
        )?;

        // TODO(b/431814103): Consider ATT MTU limits when configuring multiple
        // ASEs. If the encoded request exceeds the current MTU, we may
        // need to break it into multiple Control Point writes.
        let op = AseControlOperation::ConfigQos { qos_configurations, responses: vec![] };

        self.perform_and_verify_operation(op).await
    }

    /// Performs the Enable operation on one or more ASEs.
    ///
    /// # Arguments
    /// * `ases_with_metadata` - A vector of `AseIdWithMetadata` structs
    ///   specifying the target ASE IDs and their codec metadata.
    ///
    /// # Returns
    /// On success, returns an [`AseControlOperationOutcome`] containing the
    /// results of the operation.
    pub async fn enable(
        &mut self,
        ases_with_metadata: Vec<AseIdWithMetadata>,
    ) -> Result<AseControlOperationOutcome, Error> {
        self.validate_arguments(
            AseControlPointOpcode::Enable,
            ases_with_metadata.iter().map(|a| &a.ase_id),
        )?;

        let op = AseControlOperation::Enable { ases_with_metadata, responses: vec![] };

        self.perform_and_verify_operation(op).await
    }

    /// Performs the Receiver Start Ready operation on one or more Source ASEs.
    ///
    /// # Arguments
    /// * `ases` - A vector of `AseId`s to start.
    ///
    /// # Returns
    /// On success, returns an [`AseControlOperationOutcome`] containing the
    /// results of the operation.
    pub async fn receiver_start_ready(
        &mut self,
        ases: Vec<AseId>,
    ) -> Result<AseControlOperationOutcome, Error> {
        self.validate_arguments(AseControlPointOpcode::ReceiverStartReady, &ases)?;
        self.verify_ase_directions(
            &ases,
            AseControlPointOpcode::ReceiverStartReady,
            AudioDirection::Source,
        )?;

        let op = AseControlOperation::ReceiverStartReady { ases };

        self.perform_and_verify_operation(op).await
    }

    /// Performs the Disable operation on one or more ASEs.
    ///
    /// # Arguments
    /// * `ases` - A vector of `AseId`s to disable.
    ///
    /// # Returns
    /// On success, returns an [`AseControlOperationOutcome`] containing the
    /// results of the operation.
    pub async fn disable(&mut self, ases: Vec<AseId>) -> Result<AseControlOperationOutcome, Error> {
        self.validate_arguments(AseControlPointOpcode::Disable, &ases)?;

        let op = AseControlOperation::Disable { ases };

        self.perform_and_verify_operation(op).await
    }

    /// Performs the Receiver Stop Ready operation on one or more Source ASEs.
    ///
    /// # Arguments
    /// * `ases` - A vector of `AseId`s to stop.
    ///
    /// # Returns
    /// On success, returns an [`AseControlOperationOutcome`] containing the
    /// results of the operation.
    pub async fn receiver_stop_ready(
        &mut self,
        ases: Vec<AseId>,
    ) -> Result<AseControlOperationOutcome, Error> {
        self.validate_arguments(AseControlPointOpcode::ReceiverStopReady, &ases)?;
        self.verify_ase_directions(
            &ases,
            AseControlPointOpcode::ReceiverStopReady,
            AudioDirection::Source,
        )?;

        let op = AseControlOperation::ReceiverStopReady { ases };

        self.perform_and_verify_operation(op).await
    }

    /// Performs the Update Metadata operation on one or more ASEs.
    ///
    /// # Arguments
    /// * `ases_with_metadata` - A vector of `AseIdWithMetadata` structs
    ///   specifying the target ASE IDs and their new codec metadata.
    ///
    /// # Returns
    /// On success, returns an [`AseControlOperationOutcome`] containing the
    /// results of the operation.
    pub async fn update_metadata(
        &mut self,
        ases_with_metadata: Vec<AseIdWithMetadata>,
    ) -> Result<AseControlOperationOutcome, Error> {
        self.validate_arguments(
            AseControlPointOpcode::UpdateMetadata,
            ases_with_metadata.iter().map(|a| &a.ase_id),
        )?;

        let op = AseControlOperation::UpdateMetadata { ases_with_metadata, responses: vec![] };

        self.perform_and_verify_operation(op).await
    }

    /// Performs the Release operation on one or more ASEs.
    ///
    /// # Arguments
    /// * `ases` - A vector of `AseId`s to release.
    ///
    /// # Returns
    /// On success, returns an [`AseControlOperationOutcome`] containing the
    /// results of the operation.
    pub async fn release(&mut self, ases: Vec<AseId>) -> Result<AseControlOperationOutcome, Error> {
        self.validate_arguments(AseControlPointOpcode::Release, &ases)?;

        let op = AseControlOperation::Release { ases };

        self.perform_and_verify_operation(op).await
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use bt_common::core::CodecId;
    use bt_common::generic_audio::metadata_ltv::Metadata;
    use bt_gatt::connected_isochronous::{Framing, MaxTransportLatency};
    use bt_gatt::test_utils::{FakePeerService, FakeTypes};
    use bt_gatt::types::{AttributePermissions, CharacteristicProperties, CharacteristicProperty};
    use bt_gatt::Characteristic;

    const CONTROL_POINT_HANDLE: Handle = Handle(1);
    const SINK_ASE_HANDLE: Handle = Handle(2);
    const SOURCE_ASE_HANDLE: Handle = Handle(3);

    fn setup_fake_service() -> FakePeerService {
        let mut service = FakePeerService::new();
        // Add Control Point
        service.add_characteristic(
            Characteristic {
                handle: CONTROL_POINT_HANDLE,
                uuid: ASE_CONTROL_POINT_UUID,
                properties: CharacteristicProperties::WRITE_NOTIFY,
                permissions: AttributePermissions::default(),
                descriptors: vec![],
            },
            vec![],
        );
        // Add Sink ASE
        service.add_characteristic(
            Characteristic {
                handle: SINK_ASE_HANDLE,
                uuid: SINK_ASE_UUID,
                properties: CharacteristicProperties::READ_NOTIFY,
                permissions: AttributePermissions::default(),
                descriptors: vec![],
            },
            vec![0x01, 0x00], // ASE ID 1, State Idle
        );
        // Add Source ASE
        service.add_characteristic(
            Characteristic {
                handle: SOURCE_ASE_HANDLE,
                uuid: SOURCE_ASE_UUID,
                properties: CharacteristicProperties::READ_NOTIFY,
                permissions: AttributePermissions::default(),
                descriptors: vec![],
            },
            vec![0x02, 0x00], // ASE ID 2, State Idle
        );
        service
    }

    fn run_to_completion<F: std::future::Future>(fut: F) -> F::Output {
        let mut fut = std::pin::pin!(fut);
        let mut cx = futures::task::Context::from_waker(futures::task::noop_waker_ref());
        match fut.as_mut().poll(&mut cx) {
            std::task::Poll::Ready(res) => res,
            std::task::Poll::Pending => panic!("Future did not complete synchronously"),
        }
    }

    #[test]
    fn client_creation_success() {
        let service = setup_fake_service();
        let client_fut = AudioStreamControlServiceClient::<FakeTypes>::create(service.clone());
        let client = run_to_completion(client_fut).expect("client creation should succeed");

        assert_eq!(client.control_point.handle, CONTROL_POINT_HANDLE);
        assert_eq!(client.endpoints.sink.len(), 1);
        assert_eq!(client.endpoints.source.len(), 1);

        let sink = &client.endpoints.sink[&SINK_ASE_HANDLE].endpoint;
        assert_eq!(sink.ase_id, AseId(1));
        assert_eq!(sink.state, AseState::Idle);
        assert_eq!(sink.direction, AudioDirection::Sink);

        let source = &client.endpoints.source[&SOURCE_ASE_HANDLE].endpoint;
        assert_eq!(source.ase_id, AseId(2));
        assert_eq!(source.state, AseState::Idle);
        assert_eq!(source.direction, AudioDirection::Source);

        assert_eq!(client.endpoints.sink_ases(), vec![AseId(1)]);
        assert_eq!(client.endpoints.source_ases(), vec![AseId(2)]);
    }

    #[test]
    fn client_creation_missing_control_point() {
        let mut service = FakePeerService::new();
        // Only add Sink (no Control Point)
        service.add_characteristic(
            Characteristic {
                handle: SINK_ASE_HANDLE,
                uuid: SINK_ASE_UUID,
                properties: CharacteristicProperties::READ_NOTIFY,
                permissions: AttributePermissions::default(),
                descriptors: vec![],
            },
            vec![0x01, 0x00],
        );

        let client_fut = AudioStreamControlServiceClient::<FakeTypes>::create(service);
        let err = match run_to_completion(client_fut) {
            Err(e) => e,
            Ok(_) => panic!("expected error, got Ok"),
        };
        assert!(matches!(err, Error::Client(ClientError::MissingControlPointCharacteristic)));
    }

    #[test]
    fn client_creation_missing_endpoints() {
        let mut service = FakePeerService::new();
        // Only add Control Point (no endpoints)
        service.add_characteristic(
            Characteristic {
                handle: CONTROL_POINT_HANDLE,
                uuid: ASE_CONTROL_POINT_UUID,
                properties: (&[CharacteristicProperty::Write, CharacteristicProperty::Notify])
                    .into(),
                permissions: AttributePermissions::default(),
                descriptors: vec![],
            },
            vec![],
        );

        let client_fut = AudioStreamControlServiceClient::<FakeTypes>::create(service);
        let err = match run_to_completion(client_fut) {
            Err(e) => e,
            Ok(_) => panic!("expected error, got Ok"),
        };
        assert!(matches!(err, Error::Client(ClientError::MissingAudioStreamEndpoints)));
    }

    #[test]
    fn client_creation_extra_control_point() {
        let mut service = FakePeerService::new();
        // Add first Control Point
        service.add_characteristic(
            Characteristic {
                handle: CONTROL_POINT_HANDLE,
                uuid: ASE_CONTROL_POINT_UUID,
                properties: (&[CharacteristicProperty::Write, CharacteristicProperty::Notify])
                    .into(),
                permissions: AttributePermissions::default(),
                descriptors: vec![],
            },
            vec![],
        );
        // Add second Control Point
        service.add_characteristic(
            Characteristic {
                handle: Handle(4),
                uuid: ASE_CONTROL_POINT_UUID,
                properties: (&[CharacteristicProperty::Write, CharacteristicProperty::Notify])
                    .into(),
                permissions: AttributePermissions::default(),
                descriptors: vec![],
            },
            vec![],
        );

        let client_fut = AudioStreamControlServiceClient::<FakeTypes>::create(service);
        let err = match run_to_completion(client_fut) {
            Err(e) => e,
            Ok(_) => panic!("expected error, got Ok"),
        };
        assert!(matches!(err, Error::Client(ClientError::ExtraControlPointCharacteristic)));
    }

    #[test]
    fn configure_codec() {
        let mut service = setup_fake_service();
        let client_fut = AudioStreamControlServiceClient::<FakeTypes>::create(service.clone());
        let mut client = run_to_completion(client_fut).expect("client creation should succeed");

        let config1 = CodecConfiguration {
            ase_id: AseId(1),
            target_latency: TargetLatency::TargetLowLatency,
            target_phy: TargetPhy::Le1MPhy,
            codec_id: CodecId::Assigned(bt_common::core::CodingFormat::Lc3),
            codec_specific_configuration: vec![],
        };
        let config2 = CodecConfiguration {
            ase_id: AseId(2),
            target_latency: TargetLatency::TargetLowLatency,
            target_phy: TargetPhy::Le1MPhy,
            codec_id: CodecId::Assigned(bt_common::core::CodingFormat::Lc3),
            codec_specific_configuration: vec![],
        };

        #[rustfmt::skip]
        service.expect_characteristic_value(
            &CONTROL_POINT_HANDLE,
            vec![
                0x01, // Opcode: Config Codec
                0x02, // Num ASEs
                0x01, 0x01, 0x01, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, // ASE 1 Config
                0x02, 0x01, 0x01, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, // ASE 2 Config
            ],
        );

        #[rustfmt::skip]
        service.notify(
            &CONTROL_POINT_HANDLE,
            Ok(CharacteristicNotification {
                handle: CONTROL_POINT_HANDLE,
                value: vec![
                    0x01, // Opcode
                    0x02, // Num ASEs
                    0x01, 0x00, 0x00, // ASE 1 Response: Success
                    0x02, 0x03, 0x02, // ASE 2 Response: Failed (Invalid ASE ID)
                ],
                maybe_truncated: false,
            }),
        );

        #[rustfmt::skip]
        service.notify(
            &SINK_ASE_HANDLE,
            Ok(CharacteristicNotification {
                handle: SINK_ASE_HANDLE,
                value: vec![
                    0x01, // ASE ID: 1
                    0x01, // ASE State: Codec Configured
                    0x00, 0x01, 0x02, 0x0A, 0x00, 0x10, 0x27, 0x00, 0x40, 0x9C, 0x00,
                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00,
                ],
                maybe_truncated: false,
            }),
        );

        let configure_fut = client.configure_codec(vec![config1, config2]);
        let outcome = run_to_completion(configure_fut).expect("configure codec should succeed");

        assert_eq!(
            client.endpoints.sink[&SINK_ASE_HANDLE].endpoint.state,
            AseState::CodecConfigured
        );
        assert_eq!(outcome.accepted().len(), 1);
        let endpoint = &outcome.accepted()[&AseId(1)];
        let qos = endpoint.qos_parameters().unwrap();
        assert_eq!(qos.framing, Framing::Unframed);
        assert_eq!(qos.preferred_phys, vec![Phy::Le1MPhy]);
        assert_eq!(qos.preferred_retransmission_number, 2);

        assert_eq!(outcome.rejected().len(), 1);
        assert_eq!(outcome.rejected()[&AseId(2)], ResponseCode::InvalidAseId { value: 2 });
    }

    #[test]
    fn configure_codec_fail_unknown_ase_id() {
        let service = setup_fake_service();
        let client_fut = AudioStreamControlServiceClient::<FakeTypes>::create(service.clone());
        let mut client = run_to_completion(client_fut).expect("client creation should succeed");

        let config = CodecConfiguration {
            ase_id: AseId(99), // Non-existent ASE ID
            target_latency: TargetLatency::TargetLowLatency,
            target_phy: TargetPhy::Le1MPhy,
            codec_id: CodecId::Assigned(bt_common::core::CodingFormat::Lc3),
            codec_specific_configuration: vec![],
        };

        let configure_fut = client.configure_codec(vec![config]);
        let err = run_to_completion(configure_fut).expect_err("should fail due to unknown ASE ID");
        assert!(matches!(err, Error::Client(ClientError::UnknownAseId(AseId(99)))));
    }

    #[test]
    fn configure_codec_global_error() {
        let mut service = setup_fake_service();
        let client_fut = AudioStreamControlServiceClient::<FakeTypes>::create(service.clone());
        let mut client = run_to_completion(client_fut).expect("client creation should succeed");

        let config = CodecConfiguration {
            ase_id: AseId(1),
            target_latency: TargetLatency::TargetLowLatency,
            target_phy: TargetPhy::Le1MPhy,
            codec_id: CodecId::Assigned(bt_common::core::CodingFormat::Lc3),
            codec_specific_configuration: vec![],
        };

        #[rustfmt::skip]
        service.expect_characteristic_value(
            &CONTROL_POINT_HANDLE,
            vec![
                0x01, // Opcode: Config Codec
                0x01, // Num ASEs
                0x01, 0x01, 0x01, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, // ASE 1 Config
            ],
        );

        // Let's mimic server side throwing a global invalid length error.
        // (in reality this wouldn't happen because our configure codec
        // operation was encoded correctly).
        #[rustfmt::skip]
        service.notify(
            &CONTROL_POINT_HANDLE,
            Ok(CharacteristicNotification {
                handle: CONTROL_POINT_HANDLE,
                value: vec![
                    0x01, // Opcode
                    0xFF, // Num ASEs: Global Error
                    0x00, 0x02, 0x00, // ASE 0, Invalid Length, None
                ],
                maybe_truncated: false,
            }),
        );

        let configure_fut = client.configure_codec(vec![config]);
        let err = run_to_completion(configure_fut).expect_err("should fail with global error");

        assert!(matches!(
            err,
            Error::Client(ClientError::RejectedOperation(ref responses)) if matches!(
                responses.as_slice(),
                [ResponseCode::InvalidLength { .. }]
            )
        ));
    }

    #[test]
    fn configure_qos_success() {
        let mut service = setup_fake_service();
        let client_fut = AudioStreamControlServiceClient::<FakeTypes>::create(service.clone());
        let mut client = run_to_completion(client_fut).expect("client creation should succeed");

        // Pre-condition both Sink and Source endpoints to CodecConfigured with
        // valid QoS constraints
        let sink_value = vec![
            0x01, // ASE ID: 1
            0x01, // ASE State: Codec Configured
            0x00, 0x01, 0x02, 0x0A, 0x00, 0x10, 0x27, 0x00, 0x40, 0x9C, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00,
        ];
        client.endpoints.sink.get_mut(&SINK_ASE_HANDLE).unwrap().endpoint =
            AudioStreamEndpoint::from_char_value(
                SINK_ASE_HANDLE,
                AudioDirection::Sink,
                &sink_value,
            )
            .unwrap();

        let source_value = vec![
            0x02, // ASE ID: 2
            0x01, // ASE State: Codec Configured
            0x00, 0x01, 0x02, 0x0A, 0x00, 0x10, 0x27, 0x00, 0x40, 0x9C, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00,
        ];
        client.endpoints.source.get_mut(&SOURCE_ASE_HANDLE).unwrap().endpoint =
            AudioStreamEndpoint::from_char_value(
                SOURCE_ASE_HANDLE,
                AudioDirection::Source,
                &source_value,
            )
            .unwrap();

        // Request 1 (Preferred): Resolves constraints for AseId(1) from the
        // cache
        let req1 = QosConfigurationRequest::Preferred {
            ase_id: AseId(1),
            cig_id: CigId::try_from(1).unwrap(),
            cis_id: CisId::try_from(1).unwrap(),
            sdu_interval: SduInterval::try_from(std::time::Duration::from_micros(10000)).unwrap(),
            max_sdu: MaxSdu::try_from(100).unwrap(),
        };

        // Request 2 (Custom): Custom configuration for AseId(2)
        let req2 = QosConfigurationRequest::Custom(QosConfiguration {
            ase_id: AseId(2),
            cig_id: CigId::try_from(1).unwrap(),
            cis_id: CisId::try_from(2).unwrap(),
            sdu_interval: SduInterval::try_from(std::time::Duration::from_micros(10000)).unwrap(),
            framing: Framing::Unframed,
            phy: vec![Phy::Le1MPhy],
            max_sdu: MaxSdu::try_from(100).unwrap(),
            retransmission_number: 2,
            max_transport_latency: MaxTransportLatency::try_from(std::time::Duration::from_millis(
                10,
            ))
            .unwrap(),
            presentation_delay: PresentationDelay { microseconds: 40000 },
        });

        #[rustfmt::skip]
        service.expect_characteristic_value(
            &CONTROL_POINT_HANDLE,
            vec![
                0x02, // Opcode: Config QoS
                0x02, // Num ASEs: 2
                0x01, // ASE ID: 1
                0x01, 0x01, 0x10, 0x27, 0x00, 0x00, 0x01, 0x64, 0x00, 0x02, 0x0A, 0x00, 0x10, 0x27, 0x00, // ASE 1 Preferred QoS
                0x02, // ASE ID: 2
                0x01, 0x02, 0x10, 0x27, 0x00, 0x00, 0x01, 0x64, 0x00, 0x02, 0x0A, 0x00, 0x40, 0x9C, 0x00, // ASE 2 Custom QoS
            ],
        );

        #[rustfmt::skip]
        service.notify(
            &CONTROL_POINT_HANDLE,
            Ok(CharacteristicNotification {
                handle: CONTROL_POINT_HANDLE,
                value: vec![
                    0x02, // Opcode: Config QoS
                    0x02, // Num ASEs: 2
                    0x01, 0x00, 0x00, // ASE ID: 1, Success
                    0x02, 0x00, 0x00, // ASE ID: 2, Success
                ],
                maybe_truncated: false,
            }),
        );

        #[rustfmt::skip]
        service.notify(
            &SINK_ASE_HANDLE,
            Ok(CharacteristicNotification {
                handle: SINK_ASE_HANDLE,
                value: vec![
                    0x01, // ASE ID: 1
                    0x02, // ASE State: QoS Configured
                    0x01, 0x01, 0x10, 0x27, 0x00, 0x00, 0x01, 0x64, 0x00, 0x02, 0x0A, 0x00, 0x40, 0x9C, 0x00,
                ],
                maybe_truncated: false,
            }),
        );

        #[rustfmt::skip]
        service.notify(
            &SOURCE_ASE_HANDLE,
            Ok(CharacteristicNotification {
                handle: SOURCE_ASE_HANDLE,
                value: vec![
                    0x02, // ASE ID: 2
                    0x02, // ASE State: QoS Configured
                    0x01, 0x02, 0x10, 0x27, 0x00, 0x00, 0x01, 0x64, 0x00, 0x02, 0x0A, 0x00, 0x40, 0x9C, 0x00,
                ],
                maybe_truncated: false,
            }),
        );

        let configure_qos_fut = client.configure_qos(vec![req1, req2]);
        let outcome = run_to_completion(configure_qos_fut).expect("configure QoS should succeed");

        assert_eq!(outcome.rejected().len(), 0);
        assert_eq!(client.endpoints.sink[&SINK_ASE_HANDLE].endpoint.state, AseState::QosConfigured);
        assert_eq!(
            client.endpoints.source[&SOURCE_ASE_HANDLE].endpoint.state,
            AseState::QosConfigured
        );
    }

    #[test]
    fn configure_qos_fail_invalid_start_state() {
        let service = setup_fake_service();
        let client_fut = AudioStreamControlServiceClient::<FakeTypes>::create(service.clone());
        let mut client = run_to_completion(client_fut).expect("client creation should succeed");

        // Transition the sink ASE to Streaming state to test client-side
        // validation.
        let streaming_value = vec![
            0x01, // ASE ID: 1
            0x04, // ASE State: Streaming
            0x01, 0x01, 0x00,
        ];
        client.endpoints.sink.get_mut(&SINK_ASE_HANDLE).unwrap().endpoint =
            AudioStreamEndpoint::from_char_value(
                SINK_ASE_HANDLE,
                AudioDirection::Sink,
                &streaming_value,
            )
            .unwrap();

        let qos_config = QosConfiguration {
            ase_id: AseId(1),
            cig_id: CigId::try_from(1).unwrap(),
            cis_id: CisId::try_from(1).unwrap(),
            sdu_interval: SduInterval::try_from(std::time::Duration::from_micros(10000)).unwrap(),
            framing: Framing::Unframed,
            phy: vec![Phy::Le1MPhy],
            max_sdu: MaxSdu::try_from(100).unwrap(),
            retransmission_number: 2,
            max_transport_latency: MaxTransportLatency::try_from(std::time::Duration::from_millis(
                10,
            ))
            .unwrap(),
            presentation_delay: PresentationDelay { microseconds: 40000 },
        };

        let configure_qos_fut =
            client.configure_qos(vec![QosConfigurationRequest::Custom(qos_config)]);
        let err =
            run_to_completion(configure_qos_fut).expect_err("should fail client-side validation");

        assert!(matches!(
            err,
            Error::Client(ClientError::InvalidStartState {
                ase_id: AseId(1),
                opcode: AseControlPointOpcode::ConfigQos,
                actual: AseState::Streaming,
            })
        ));
    }

    #[test]
    fn configure_codec_fail_malformed_control_point_notification() {
        let mut service = setup_fake_service();
        let client_fut = AudioStreamControlServiceClient::<FakeTypes>::create(service.clone());
        let mut client = run_to_completion(client_fut).expect("client creation should succeed");

        let config = CodecConfiguration {
            ase_id: AseId(1),
            target_latency: TargetLatency::TargetLowLatency,
            target_phy: TargetPhy::Le1MPhy,
            codec_id: CodecId::Assigned(bt_common::core::CodingFormat::Lc3),
            codec_specific_configuration: vec![],
        };

        #[rustfmt::skip]
        service.expect_characteristic_value(
            &CONTROL_POINT_HANDLE,
            vec![
                0x01, // Opcode: Config Codec
                0x01, // Num ASEs
                0x01, 0x01, 0x01, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, // ASE 1 Config
            ],
        );

        #[rustfmt::skip]
        service.notify(
            &CONTROL_POINT_HANDLE,
            Ok(CharacteristicNotification {
                handle: CONTROL_POINT_HANDLE,
                value: vec![0x01], // Only 1 byte, malformed (< 2 bytes)
                maybe_truncated: false,
            }),
        );

        let configure_fut = client.configure_codec(vec![config]);
        let err = run_to_completion(configure_fut).expect_err("should fail with decoding error");

        assert!(matches!(
            err,
            Error::Gatt(bt_gatt::types::Error::Encoding(
                bt_common::packet_encoding::Error::UnexpectedDataLength
            ))
        ));
    }

    #[test]
    fn configure_codec_fail_malformed_ase_notification() {
        let mut service = setup_fake_service();
        let client_fut = AudioStreamControlServiceClient::<FakeTypes>::create(service.clone());
        let mut client = run_to_completion(client_fut).expect("client creation should succeed");

        let config = CodecConfiguration {
            ase_id: AseId(1),
            target_latency: TargetLatency::TargetLowLatency,
            target_phy: TargetPhy::Le1MPhy,
            codec_id: CodecId::Assigned(bt_common::core::CodingFormat::Lc3),
            codec_specific_configuration: vec![],
        };

        #[rustfmt::skip]
        service.expect_characteristic_value(
            &CONTROL_POINT_HANDLE,
            vec![
                0x01, // Opcode: Config Codec
                0x01, // Num ASEs
                0x01, 0x01, 0x01, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, // ASE 1 Config
            ],
        );

        #[rustfmt::skip]
        service.notify(
            &CONTROL_POINT_HANDLE,
            Ok(CharacteristicNotification {
                handle: CONTROL_POINT_HANDLE,
                value: vec![
                    0x01, // Opcode: Config Codec
                    0x01, // Num ASEs: 1
                    0x01, 0x00, 0x00, // ASE 1 Response: Success
                ],
                maybe_truncated: false,
            }),
        );

        #[rustfmt::skip]
        service.notify(
            &SINK_ASE_HANDLE,
            Ok(CharacteristicNotification {
                handle: SINK_ASE_HANDLE,
                value: vec![0x01], // Only 1 byte, malformed (< 2 bytes)
                maybe_truncated: false,
            }),
        );

        let configure_fut = client.configure_codec(vec![config]);
        let err = run_to_completion(configure_fut).expect_err("should fail with conversion error");

        assert!(matches!(
            err,
            Error::Gatt(bt_gatt::types::Error::Conversion(ref s)) if s.contains("Failed to decode AudioStreamEndpoint")
        ));
    }

    #[test]
    fn configure_codec_fail_unexpected_state_updates_local_cache() {
        let mut service = setup_fake_service();
        let client_fut = AudioStreamControlServiceClient::<FakeTypes>::create(service.clone());
        let mut client = run_to_completion(client_fut).expect("client creation should succeed");

        let config1 = CodecConfiguration {
            ase_id: AseId(1),
            target_latency: TargetLatency::TargetLowLatency,
            target_phy: TargetPhy::Le1MPhy,
            codec_id: CodecId::Assigned(bt_common::core::CodingFormat::Lc3),
            codec_specific_configuration: vec![],
        };
        let config2 = CodecConfiguration {
            ase_id: AseId(2),
            target_latency: TargetLatency::TargetLowLatency,
            target_phy: TargetPhy::Le1MPhy,
            codec_id: CodecId::Assigned(bt_common::core::CodingFormat::Lc3),
            codec_specific_configuration: vec![],
        };

        #[rustfmt::skip]
        service.expect_characteristic_value(
            &CONTROL_POINT_HANDLE,
            vec![
                0x01, // Opcode: Config Codec
                0x02, // Num ASEs
                0x01, 0x01, 0x01, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, // ASE 1 Config
                0x02, 0x01, 0x01, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, // ASE 2 Config
            ],
        );

        #[rustfmt::skip]
        service.notify(
            &CONTROL_POINT_HANDLE,
            Ok(CharacteristicNotification {
                handle: CONTROL_POINT_HANDLE,
                value: vec![
                    0x01, // Opcode: Config Codec
                    0x02, // Num ASEs: 2
                    0x01, 0x00, 0x00, // ASE 1 Response: Success
                    0x02, 0x00, 0x00, // ASE 2 Response: Success
                ],
                maybe_truncated: false,
            }),
        );

        // Notify ASE 1 with Codec Configured (valid!)
        #[rustfmt::skip]
        service.notify(
            &SINK_ASE_HANDLE,
            Ok(CharacteristicNotification {
                handle: SINK_ASE_HANDLE,
                value: vec![
                    0x01, // ASE ID: 1
                    0x01, // ASE State: Codec Configured
                    0x00, 0x01, 0x02, 0x0A, 0x00, 0x10, 0x27, 0x00, 0x40, 0x9C, 0x00,
                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00,
                ],
                maybe_truncated: false,
            }),
        );

        // Notify ASE 2 with Streaming (invalid for Config Codec!)
        #[rustfmt::skip]
        service.notify(
            &SOURCE_ASE_HANDLE,
            Ok(CharacteristicNotification {
                handle: SOURCE_ASE_HANDLE,
                value: vec![
                    0x02, // ASE ID: 2
                    0x04, // ASE State: Streaming (unexpected!)
                    0x01, // CIG ID: 1
                    0x02, // CIS ID: 2
                    0x00, // Metadata Length: 0
                ],
                maybe_truncated: false,
            }),
        );

        let configure_fut = client.configure_codec(vec![config1, config2]);
        let err = run_to_completion(configure_fut)
            .expect_err("should fail with unexpected state transition");

        assert!(matches!(
            err,
            Error::Client(ClientError::UnexpectedStateTransition {
                ase_id: AseId(2),
                expected: AseState::CodecConfigured,
                actual: AseState::Streaming,
            })
        ));

        // Both endpoints in our local cache MUST be updated with the latest
        // notified states!
        assert_eq!(
            client.endpoints.sink[&SINK_ASE_HANDLE].endpoint.state,
            AseState::CodecConfigured
        );
        assert_eq!(client.endpoints.source[&SOURCE_ASE_HANDLE].endpoint.state, AseState::Streaming);
    }

    #[test]
    fn enable_success() {
        let mut service = setup_fake_service();
        let client_fut = AudioStreamControlServiceClient::<FakeTypes>::create(service.clone());
        let mut client = run_to_completion(client_fut).expect("client creation should succeed");

        // Pre-condition SINK_ASE_HANDLE to QosConfigured state
        let sink_value = vec![
            0x01, // ASE ID: 1
            0x02, // ASE State: QoS Configured
            0x01, 0x01, 0x10, 0x27, 0x00, 0x00, 0x01, 0x64, 0x00, 0x02, 0x0A, 0x00, 0x40, 0x9C,
            0x00,
        ];
        client.endpoints.sink.get_mut(&SINK_ASE_HANDLE).unwrap().endpoint =
            AudioStreamEndpoint::from_char_value(
                SINK_ASE_HANDLE,
                AudioDirection::Sink,
                &sink_value,
            )
            .unwrap();

        let enable_req = AseIdWithMetadata { ase_id: AseId(1), metadata: vec![] };

        #[rustfmt::skip]
        service.expect_characteristic_value(
            &CONTROL_POINT_HANDLE,
            vec![
                0x03, // Opcode: Enable
                0x01, // Num ASEs
                0x01, // ASE ID: 1
                0x00, // Metadata Length: 0
            ],
        );

        #[rustfmt::skip]
        service.notify(
            &CONTROL_POINT_HANDLE,
            Ok(CharacteristicNotification {
                handle: CONTROL_POINT_HANDLE,
                value: vec![
                    0x03, // Opcode: Enable
                    0x01, // Num ASEs
                    0x01, 0x00, 0x00, // ASE ID: 1, Success
                ],
                maybe_truncated: false,
            }),
        );

        #[rustfmt::skip]
        service.notify(
            &SINK_ASE_HANDLE,
            Ok(CharacteristicNotification {
                handle: SINK_ASE_HANDLE,
                value: vec![
                    0x01, // ASE ID: 1
                    0x03, // ASE State: Enabling
                    0x01, // CIG ID: 1
                    0x01, // CIS ID: 1
                    0x00, // Metadata Length: 0
                ],
                maybe_truncated: false,
            }),
        );

        let enable_fut = client.enable(vec![enable_req]);
        let outcome = run_to_completion(enable_fut).expect("enable should succeed");

        assert_eq!(outcome.rejected().len(), 0);
        assert_eq!(client.endpoints.sink[&SINK_ASE_HANDLE].endpoint.state, AseState::Enabling);
    }

    #[test]
    fn enable_fail_invalid_start_state() {
        let service = setup_fake_service();
        let client_fut = AudioStreamControlServiceClient::<FakeTypes>::create(service.clone());
        let mut client = run_to_completion(client_fut).expect("client creation should succeed");

        // Transition the sink ASE to Streaming state to test client-side
        // validation.
        let streaming_value = vec![
            0x01, // ASE ID: 1
            0x04, // ASE State: Streaming
            0x01, // CIG ID: 1
            0x01, // CIS ID: 1
            0x00, // Metadata Length: 0
        ];
        client.endpoints.sink.get_mut(&SINK_ASE_HANDLE).unwrap().endpoint =
            AudioStreamEndpoint::from_char_value(
                SINK_ASE_HANDLE,
                AudioDirection::Sink,
                &streaming_value,
            )
            .unwrap();

        let enable_req = AseIdWithMetadata { ase_id: AseId(1), metadata: vec![] };

        let enable_fut = client.enable(vec![enable_req]);
        let err = run_to_completion(enable_fut).expect_err("should fail client-side validation");

        assert!(matches!(
            err,
            Error::Client(ClientError::InvalidStartState {
                ase_id: AseId(1),
                opcode: AseControlPointOpcode::Enable,
                actual: AseState::Streaming,
            })
        ));
    }

    #[test]
    fn receiver_start_ready_success() {
        let mut service = setup_fake_service();
        let client_fut = AudioStreamControlServiceClient::<FakeTypes>::create(service.clone());
        let mut client = run_to_completion(client_fut).expect("client creation should succeed");

        // Pre-condition SOURCE_ASE_HANDLE to Enabling state
        let source_value = vec![
            0x02, // ASE ID: 2
            0x03, // ASE State: Enabling
            0x01, 0x01, 0x00,
        ];
        client.endpoints.source.get_mut(&SOURCE_ASE_HANDLE).unwrap().endpoint =
            AudioStreamEndpoint::from_char_value(
                SOURCE_ASE_HANDLE,
                AudioDirection::Source,
                &source_value,
            )
            .unwrap();

        #[rustfmt::skip]
        service.expect_characteristic_value(
            &CONTROL_POINT_HANDLE,
            vec![
                0x04, // Opcode: Receiver Start Ready
                0x01, // Num ASEs
                0x02, // ASE ID: 2
            ],
        );

        #[rustfmt::skip]
        service.notify(
            &CONTROL_POINT_HANDLE,
            Ok(CharacteristicNotification {
                handle: CONTROL_POINT_HANDLE,
                value: vec![
                    0x04, // Opcode: Receiver Start Ready
                    0x01, // Num ASEs
                    0x02, 0x00, 0x00, // ASE ID: 2, Success
                ],
                maybe_truncated: false,
            }),
        );

        #[rustfmt::skip]
        service.notify(
            &SOURCE_ASE_HANDLE,
            Ok(CharacteristicNotification {
                handle: SOURCE_ASE_HANDLE,
                value: vec![
                    0x02, // ASE ID: 2
                    0x04, // ASE State: Streaming
                    0x01, // CIG ID: 1
                    0x01, // CIS ID: 1
                    0x00, // Metadata Length: 0
                ],
                maybe_truncated: false,
            }),
        );

        let start_fut = client.receiver_start_ready(vec![AseId(2)]);
        let outcome = run_to_completion(start_fut).expect("receiver start ready should succeed");

        assert_eq!(outcome.rejected().len(), 0);
        assert_eq!(client.endpoints.source[&SOURCE_ASE_HANDLE].endpoint.state, AseState::Streaming);
    }

    #[test]
    fn receiver_start_ready_fail_invalid_start_state() {
        let service = setup_fake_service();
        let client_fut = AudioStreamControlServiceClient::<FakeTypes>::create(service.clone());
        let mut client = run_to_completion(client_fut).expect("client creation should succeed");

        // ASE 2 (Source) is in Idle state, which is invalid for
        // ReceiverStartReady
        let start_fut = client.receiver_start_ready(vec![AseId(2)]);
        let err = run_to_completion(start_fut).expect_err("should fail client-side validation");

        assert!(matches!(
            err,
            Error::Client(ClientError::InvalidStartState {
                ase_id: AseId(2),
                opcode: AseControlPointOpcode::ReceiverStartReady,
                actual: AseState::Idle,
            })
        ));
    }

    #[test]
    fn receiver_start_ready_fail_invalid_direction() {
        let service = setup_fake_service();
        let client_fut = AudioStreamControlServiceClient::<FakeTypes>::create(service.clone());
        let mut client = run_to_completion(client_fut).expect("client creation should succeed");

        // Pre-condition SINK_ASE_HANDLE (ASE 1) to Enabling state
        let sink_value = vec![
            0x01, // ASE ID: 1
            0x03, // ASE State: Enabling
            0x01, 0x01, 0x00,
        ];
        client.endpoints.sink.get_mut(&SINK_ASE_HANDLE).unwrap().endpoint =
            AudioStreamEndpoint::from_char_value(
                SINK_ASE_HANDLE,
                AudioDirection::Sink,
                &sink_value,
            )
            .unwrap();

        let start_fut = client.receiver_start_ready(vec![AseId(1)]);
        let err = run_to_completion(start_fut).expect_err("should fail client-side validation");

        assert!(matches!(
            err,
            Error::Client(ClientError::InvalidDirection {
                ase_id: AseId(1),
                opcode: AseControlPointOpcode::ReceiverStartReady,
                direction: AudioDirection::Sink,
            })
        ));
    }

    #[test]
    fn receiver_start_ready_rejected() {
        let mut service = setup_fake_service();
        let client_fut = AudioStreamControlServiceClient::<FakeTypes>::create(service.clone());
        let mut client = run_to_completion(client_fut).expect("client creation should succeed");

        // Pre-condition SOURCE_ASE_HANDLE to Enabling state
        let source_value = vec![
            0x02, // ASE ID: 2
            0x03, // ASE State: Enabling
            0x01, 0x01, 0x00,
        ];
        client.endpoints.source.get_mut(&SOURCE_ASE_HANDLE).unwrap().endpoint =
            AudioStreamEndpoint::from_char_value(
                SOURCE_ASE_HANDLE,
                AudioDirection::Source,
                &source_value,
            )
            .unwrap();

        #[rustfmt::skip]
        service.expect_characteristic_value(
            &CONTROL_POINT_HANDLE,
            vec![
                0x04, // Opcode: Receiver Start Ready
                0x01, // Num ASEs
                0x02, // ASE ID: 2
            ],
        );

        // Notify rejection from server due to Insufficient Resources (Response
        // Code 0x0D)
        #[rustfmt::skip]
        service.notify(
            &CONTROL_POINT_HANDLE,
            Ok(CharacteristicNotification {
                handle: CONTROL_POINT_HANDLE,
                value: vec![
                    0x04, // Opcode: Receiver Start Ready
                    0x01, // Num ASEs
                    0x02, 0x0D, 0x00, // ASE ID: 2, Insufficient Resources
                ],
                maybe_truncated: false,
            }),
        );

        let start_fut = client.receiver_start_ready(vec![AseId(2)]);
        let outcome = run_to_completion(start_fut).expect("receiver start ready should succeed");

        assert_eq!(outcome.rejected().len(), 1);
        assert_eq!(
            outcome.rejected()[&AseId(2)],
            ResponseCode::InsufficientResources { ase_id: AseId(2) }
        );
        // The state should remain Enabling
        assert_eq!(client.endpoints.source[&SOURCE_ASE_HANDLE].endpoint.state, AseState::Enabling);
    }

    #[test]
    fn disable_success() {
        let mut service = setup_fake_service();
        let client_fut = AudioStreamControlServiceClient::<FakeTypes>::create(service.clone());
        let mut client = run_to_completion(client_fut).expect("client creation should succeed");

        // Pre-condition SINK_ASE_HANDLE (ASE 1) to Streaming state
        let sink_value = vec![
            0x01, // ASE ID: 1
            0x04, // ASE State: Streaming
            0x01, 0x01, 0x00,
        ];
        client.endpoints.sink.get_mut(&SINK_ASE_HANDLE).unwrap().endpoint =
            AudioStreamEndpoint::from_char_value(
                SINK_ASE_HANDLE,
                AudioDirection::Sink,
                &sink_value,
            )
            .unwrap();

        // Pre-condition SOURCE_ASE_HANDLE (ASE 2) to Streaming state
        let source_value = vec![
            0x02, // ASE ID: 2
            0x04, // ASE State: Streaming
            0x01, 0x01, 0x00,
        ];
        client.endpoints.source.get_mut(&SOURCE_ASE_HANDLE).unwrap().endpoint =
            AudioStreamEndpoint::from_char_value(
                SOURCE_ASE_HANDLE,
                AudioDirection::Source,
                &source_value,
            )
            .unwrap();

        #[rustfmt::skip]
        service.expect_characteristic_value(
            &CONTROL_POINT_HANDLE,
            vec![
                0x05, // Opcode: Disable
                0x02, // Num ASEs
                0x01, // ASE ID: 1
                0x02, // ASE ID: 2
            ],
        );

        #[rustfmt::skip]
        service.notify(
            &CONTROL_POINT_HANDLE,
            Ok(CharacteristicNotification {
                handle: CONTROL_POINT_HANDLE,
                value: vec![
                    0x05, // Opcode: Disable
                    0x02, // Num ASEs
                    0x01, 0x00, 0x00, // ASE ID: 1, Success
                    0x02, 0x00, 0x00, // ASE ID: 2, Success
                ],
                maybe_truncated: false,
            }),
        );

        // Expected state updates:
        // Sink ASE transitions back to QoS Configured (no Disabling state)
        #[rustfmt::skip]
        service.notify(
            &SINK_ASE_HANDLE,
            Ok(CharacteristicNotification {
                handle: SINK_ASE_HANDLE,
                value: vec![
                    0x01, // ASE ID: 1
                    0x02, // ASE State: QoS Configured
                    0x01, 0x01, 0x10, 0x27, 0x00, 0x00, 0x01, 0x64, 0x00, 0x02, 0x0A, 0x00, 0x40, 0x9C, 0x00,
                ],
                maybe_truncated: false,
            }),
        );

        // Source ASE transitions to Disabling
        #[rustfmt::skip]
        service.notify(
            &SOURCE_ASE_HANDLE,
            Ok(CharacteristicNotification {
                handle: SOURCE_ASE_HANDLE,
                value: vec![
                    0x02, // ASE ID: 2
                    0x05, // ASE State: Disabling
                    0x01, 0x01, 0x00,
                ],
                maybe_truncated: false,
            }),
        );

        let disable_fut = client.disable(vec![AseId(1), AseId(2)]);
        let outcome = run_to_completion(disable_fut).expect("disable should succeed");

        assert_eq!(outcome.rejected().len(), 0);
        assert_eq!(client.endpoints.sink[&SINK_ASE_HANDLE].endpoint.state, AseState::QosConfigured);
        assert_eq!(client.endpoints.source[&SOURCE_ASE_HANDLE].endpoint.state, AseState::Disabling);
    }

    #[test]
    fn disable_fail_invalid_start_state() {
        let service = setup_fake_service();
        let client_fut = AudioStreamControlServiceClient::<FakeTypes>::create(service.clone());
        let mut client = run_to_completion(client_fut).expect("client creation should succeed");

        // ASE 1 is in Idle state, which is an invalid starting state for
        // Disable
        let disable_fut = client.disable(vec![AseId(1)]);
        let err = run_to_completion(disable_fut).expect_err("should fail client-side validation");

        assert!(matches!(
            err,
            Error::Client(ClientError::InvalidStartState {
                ase_id: AseId(1),
                opcode: AseControlPointOpcode::Disable,
                actual: AseState::Idle,
            })
        ));
    }

    #[test]
    fn receiver_stop_ready_success() {
        let mut service = setup_fake_service();
        let client_fut = AudioStreamControlServiceClient::<FakeTypes>::create(service.clone());
        let mut client = run_to_completion(client_fut).expect("client creation should succeed");

        // Pre-condition SOURCE_ASE_HANDLE (ASE 2) to Disabling state
        let source_value = vec![
            0x02, // ASE ID: 2
            0x05, // ASE State: Disabling
            0x01, 0x01, 0x00,
        ];
        client.endpoints.source.get_mut(&SOURCE_ASE_HANDLE).unwrap().endpoint =
            AudioStreamEndpoint::from_char_value(
                SOURCE_ASE_HANDLE,
                AudioDirection::Source,
                &source_value,
            )
            .unwrap();

        #[rustfmt::skip]
        service.expect_characteristic_value(
            &CONTROL_POINT_HANDLE,
            vec![
                0x06, // Opcode: Receiver Stop Ready
                0x01, // Num ASEs
                0x02, // ASE ID: 2
            ],
        );

        #[rustfmt::skip]
        service.notify(
            &CONTROL_POINT_HANDLE,
            Ok(CharacteristicNotification {
                handle: CONTROL_POINT_HANDLE,
                value: vec![
                    0x06, // Opcode: Receiver Stop Ready
                    0x01, // Num ASEs
                    0x02, 0x00, 0x00, // ASE ID: 2, Success
                ],
                maybe_truncated: false,
            }),
        );

        // Expected state transitions back to QoS Configured
        #[rustfmt::skip]
        service.notify(
            &SOURCE_ASE_HANDLE,
            Ok(CharacteristicNotification {
                handle: SOURCE_ASE_HANDLE,
                value: vec![
                    0x02, // ASE ID: 2
                    0x02, // ASE State: QoS Configured
                    0x01, 0x01, 0x10, 0x27, 0x00, 0x00, 0x01, 0x64, 0x00, 0x02, 0x0A, 0x00, 0x40, 0x9C, 0x00,
                ],
                maybe_truncated: false,
            }),
        );

        let stop_fut = client.receiver_stop_ready(vec![AseId(2)]);
        let outcome = run_to_completion(stop_fut).expect("receiver stop ready should succeed");

        assert_eq!(outcome.rejected().len(), 0);
        assert_eq!(
            client.endpoints.source[&SOURCE_ASE_HANDLE].endpoint.state,
            AseState::QosConfigured
        );
    }

    #[test]
    fn receiver_stop_ready_fail_invalid_direction() {
        let service = setup_fake_service();
        let client_fut = AudioStreamControlServiceClient::<FakeTypes>::create(service.clone());
        let mut client = run_to_completion(client_fut).expect("client creation should succeed");

        // Pre-condition SINK_ASE_HANDLE (ASE 1) to Disabling (or other state)
        let sink_value = vec![
            0x01, // ASE ID: 1
            0x05, // ASE State: Disabling
            0x01, 0x01, 0x00,
        ];
        client.endpoints.sink.get_mut(&SINK_ASE_HANDLE).unwrap().endpoint =
            AudioStreamEndpoint::from_char_value(
                SINK_ASE_HANDLE,
                AudioDirection::Sink,
                &sink_value,
            )
            .unwrap();

        let stop_fut = client.receiver_stop_ready(vec![AseId(1)]);
        let err = run_to_completion(stop_fut).expect_err("should fail client-side validation");

        assert!(matches!(
            err,
            Error::Client(ClientError::InvalidDirection {
                ase_id: AseId(1),
                opcode: AseControlPointOpcode::ReceiverStopReady,
                direction: AudioDirection::Sink,
            })
        ));
    }

    #[test]
    fn receiver_stop_ready_fail_invalid_start_state() {
        let service = setup_fake_service();
        let client_fut = AudioStreamControlServiceClient::<FakeTypes>::create(service.clone());
        let mut client = run_to_completion(client_fut).expect("client creation should succeed");

        // Source ASE is in Idle state, which is invalid starting state for
        // ReceiverStopReady
        let stop_fut = client.receiver_stop_ready(vec![AseId(2)]);
        let err = run_to_completion(stop_fut).expect_err("should fail client-side validation");

        assert!(matches!(
            err,
            Error::Client(ClientError::InvalidStartState {
                ase_id: AseId(2),
                opcode: AseControlPointOpcode::ReceiverStopReady,
                actual: AseState::Idle,
            })
        ));
    }

    #[test]
    fn receiver_stop_ready_fail_unknown_ase_id() {
        let service = setup_fake_service();
        let client_fut = AudioStreamControlServiceClient::<FakeTypes>::create(service);
        let mut client = run_to_completion(client_fut).expect("client creation should succeed");

        let stop_fut = client.receiver_stop_ready(vec![AseId(99)]);
        let err = run_to_completion(stop_fut).expect_err("should fail for unknown ASE ID");

        assert!(matches!(err, Error::Client(ClientError::UnknownAseId(AseId(99)))));
    }

    #[test]
    fn update_metadata_success() {
        let mut service = setup_fake_service();
        let client_fut = AudioStreamControlServiceClient::<FakeTypes>::create(service.clone());
        let mut client = run_to_completion(client_fut).expect("client creation should succeed");

        // Pre-condition SOURCE_ASE_HANDLE (ASE 2) to Streaming state
        let source_value = vec![
            0x02, // ASE ID: 2
            0x04, // ASE State: Streaming
            0x01, 0x01, 0x00,
        ];
        client.endpoints.source.get_mut(&SOURCE_ASE_HANDLE).unwrap().endpoint =
            AudioStreamEndpoint::from_char_value(
                SOURCE_ASE_HANDLE,
                AudioDirection::Source,
                &source_value,
            )
            .unwrap();

        let update_req = AseIdWithMetadata {
            ase_id: AseId(2),
            metadata: vec![Metadata::AudioActiveState(true)],
        };

        #[rustfmt::skip]
        service.expect_characteristic_value(
            &CONTROL_POINT_HANDLE,
            vec![
                0x07, // Opcode: Update Metadata
                0x01, // Num ASEs
                0x02, // ASE ID: 2
                0x03, // Metadata Length: 3
                0x02, 0x08, 0x01, // Metadata: AudioActiveState(true)
            ],
        );

        #[rustfmt::skip]
        service.notify(
            &CONTROL_POINT_HANDLE,
            Ok(CharacteristicNotification {
                handle: CONTROL_POINT_HANDLE,
                value: vec![
                    0x07, // Opcode: Update Metadata
                    0x01, // Num ASEs
                    0x02, 0x00, 0x00, // ASE ID: 2, Success
                ],
                maybe_truncated: false,
            }),
        );

        // ASE remains in Streaming state
        #[rustfmt::skip]
        service.notify(
            &SOURCE_ASE_HANDLE,
            Ok(CharacteristicNotification {
                handle: SOURCE_ASE_HANDLE,
                value: vec![
                    0x02, // ASE ID: 2
                    0x04, // ASE State: Streaming
                    0x01, 0x01, 0x00,
                ],
                maybe_truncated: false,
            }),
        );

        let update_fut = client.update_metadata(vec![update_req]);
        let outcome = run_to_completion(update_fut).expect("update metadata should succeed");

        assert_eq!(outcome.rejected().len(), 0);
        assert_eq!(client.endpoints.source[&SOURCE_ASE_HANDLE].endpoint.state, AseState::Streaming);
    }

    #[test]
    fn update_metadata_fail_invalid_start_state() {
        let service = setup_fake_service();
        let client_fut = AudioStreamControlServiceClient::<FakeTypes>::create(service.clone());
        let mut client = run_to_completion(client_fut).expect("client creation should succeed");

        // Source ASE is in Idle state, which is invalid starting state for
        // UpdateMetadata
        let update_req = AseIdWithMetadata { ase_id: AseId(2), metadata: vec![] };

        let update_fut = client.update_metadata(vec![update_req]);
        let err = run_to_completion(update_fut).expect_err("should fail client-side validation");

        assert!(matches!(
            err,
            Error::Client(ClientError::InvalidStartState {
                ase_id: AseId(2),
                opcode: AseControlPointOpcode::UpdateMetadata,
                actual: AseState::Idle,
            })
        ));
    }

    #[test]
    fn release_success_to_idle() {
        let mut service = setup_fake_service();
        let client_fut = AudioStreamControlServiceClient::<FakeTypes>::create(service.clone());
        let mut client = run_to_completion(client_fut).expect("client creation should succeed");

        // Pre-condition SOURCE_ASE_HANDLE (ASE 2) to Streaming state
        let source_value = vec![
            0x02, // ASE ID: 2
            0x04, // ASE State: Streaming
            0x01, 0x01, 0x00,
        ];
        client.endpoints.source.get_mut(&SOURCE_ASE_HANDLE).unwrap().endpoint =
            AudioStreamEndpoint::from_char_value(
                SOURCE_ASE_HANDLE,
                AudioDirection::Source,
                &source_value,
            )
            .unwrap();

        #[rustfmt::skip]
        service.expect_characteristic_value(
            &CONTROL_POINT_HANDLE,
            vec![
                0x08, // Opcode: Release
                0x01, // Num ASEs
                0x02, // ASE ID: 2
            ],
        );

        #[rustfmt::skip]
        service.notify(
            &CONTROL_POINT_HANDLE,
            Ok(CharacteristicNotification {
                handle: CONTROL_POINT_HANDLE,
                value: vec![
                    0x08, // Opcode: Release
                    0x01, // Num ASEs
                    0x02, 0x00, 0x00, // ASE ID: 2, Success
                ],
                maybe_truncated: false,
            }),
        );

        // Expected state transitions back to Idle
        #[rustfmt::skip]
        service.notify(
            &SOURCE_ASE_HANDLE,
            Ok(CharacteristicNotification {
                handle: SOURCE_ASE_HANDLE,
                value: vec![
                    0x02, // ASE ID: 2
                    0x00, // ASE State: Idle
                ],
                maybe_truncated: false,
            }),
        );

        let release_fut = client.release(vec![AseId(2)]);
        let outcome = run_to_completion(release_fut).expect("release should succeed");

        assert_eq!(outcome.rejected().len(), 0);
        assert_eq!(client.endpoints.source[&SOURCE_ASE_HANDLE].endpoint.state, AseState::Idle);
    }

    #[test]
    fn release_success_to_codec_configured() {
        let mut service = setup_fake_service();
        let client_fut = AudioStreamControlServiceClient::<FakeTypes>::create(service.clone());
        let mut client = run_to_completion(client_fut).expect("client creation should succeed");

        // Pre-condition SOURCE_ASE_HANDLE (ASE 2) to Streaming state
        let source_value = vec![
            0x02, // ASE ID: 2
            0x04, // ASE State: Streaming
            0x01, 0x01, 0x00,
        ];
        client.endpoints.source.get_mut(&SOURCE_ASE_HANDLE).unwrap().endpoint =
            AudioStreamEndpoint::from_char_value(
                SOURCE_ASE_HANDLE,
                AudioDirection::Source,
                &source_value,
            )
            .unwrap();

        #[rustfmt::skip]
        service.expect_characteristic_value(
            &CONTROL_POINT_HANDLE,
            vec![
                0x08, // Opcode: Release
                0x01, // Num ASEs
                0x02, // ASE ID: 2
            ],
        );

        #[rustfmt::skip]
        service.notify(
            &CONTROL_POINT_HANDLE,
            Ok(CharacteristicNotification {
                handle: CONTROL_POINT_HANDLE,
                value: vec![
                    0x08, // Opcode: Release
                    0x01, // Num ASEs
                    0x02, 0x00, 0x00, // ASE ID: 2, Success
                ],
                maybe_truncated: false,
            }),
        );

        // Expected state transitions back to Codec Configured
        #[rustfmt::skip]
        service.notify(
            &SOURCE_ASE_HANDLE,
            Ok(CharacteristicNotification {
                handle: SOURCE_ASE_HANDLE,
                value: vec![
                    0x02, // ASE ID: 2
                    0x01, // ASE State: Codec Configured
                    0x00, 0x01, 0x02, 0x0A, 0x00, 0x10, 0x27, 0x00, 0x40, 0x9C, 0x00, 0x00, 0x00, 0x00,
                    0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00,
                ],
                maybe_truncated: false,
            }),
        );

        let release_fut = client.release(vec![AseId(2)]);
        let outcome = run_to_completion(release_fut).expect("release should succeed");

        assert_eq!(outcome.rejected().len(), 0);
        assert_eq!(
            client.endpoints.source[&SOURCE_ASE_HANDLE].endpoint.state,
            AseState::CodecConfigured
        );
    }

    #[test]
    fn release_fail_invalid_start_state() {
        let service = setup_fake_service();
        let client_fut = AudioStreamControlServiceClient::<FakeTypes>::create(service.clone());
        let mut client = run_to_completion(client_fut).expect("client creation should succeed");

        // Source ASE is in Idle state, which is invalid starting state for
        // Release
        let release_fut = client.release(vec![AseId(2)]);
        let err = run_to_completion(release_fut).expect_err("should fail client-side validation");

        assert!(matches!(
            err,
            Error::Client(ClientError::InvalidStartState {
                ase_id: AseId(2),
                opcode: AseControlPointOpcode::Release,
                actual: AseState::Idle,
            })
        ));
    }
}
