// 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, 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::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 },
}

/// 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>>,
}

// 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
    }
}

/// 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 })
    }

    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::other(std::io::Error::new(
                    std::io::ErrorKind::InvalidData,
                    format!("Failed to decode AudioStreamEndpoint: {:?}", e),
                ))
            })?;
        Ok(endpoint)
    }

    fn verify_ase_ids<I>(&self, ase_ids: I) -> Result<(), Error>
    where
        I: IntoIterator<Item = AseId>,
    {
        for ase_id in ase_ids {
            if self.endpoints.lookup_by_ase_id(ase_id).is_none() {
                return Err(Error::Client(ClientError::UnknownAseId(ase_id)));
            }
        }
        Ok(())
    }

    async fn read_and_update_endpoint(
        &mut self,
        handle: &Handle,
        direction: AudioDirection,
    ) -> Result<AudioStreamEndpoint, Error> {
        let mut buf = vec![0; 255];
        let (read_bytes, _truncated) = self
            .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::other(std::io::Error::new(
                        std::io::ErrorKind::InvalidData,
                        format!("Failed to decode AudioStreamEndpoint: {:?}", e),
                    ))
                },
            )?;

        let endpoints = match direction {
            AudioDirection::Sink => &mut self.endpoints.sink,
            AudioDirection::Source => &mut self.endpoints.source,
        };
        if let Some(endpoint_handle) = endpoints.get_mut(handle) {
            endpoint_handle.endpoint = endpoint.clone();
        }
        Ok(endpoint)
    }

    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,
        opcode: u8,
        mut remaining_ases: HashSet<AseId>,
    ) -> Result<HashMap<AseId, ResponseCode>, Error> {
        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(|e| {
                bt_gatt::types::Error::other(std::io::Error::new(
                    std::io::ErrorKind::InvalidData,
                    format!("Failed to decode ControlPointNotification: {:?}", e),
                ))
            })?;
            if cp_notification.opcode != opcode {
                continue;
            }

            if cp_notification.number_of_ases == 0xFF {
                return Err(Error::Internal(format!(
                    "Server rejected operation: {:?}",
                    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,
        pending_ases: HashSet<AseId>,
    ) -> Result<AseControlOperationOutcome, Error> {
        self.write_operation(&operation).await?;

        let opcode_u8 = u8::try_from(&operation)?;
        let responses = self.collect_operation_responses(opcode_u8, pending_ases).await?;

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

        for r in responses.into_values() {
            if !r.is_success() {
                failed_responses.insert(r.ase_id(), r);
                continue;
            }
            let client_endpoint = self
                .endpoints
                .lookup_by_ase_id(r.ase_id())
                .ok_or(Error::Client(ClientError::UnknownAseId(r.ase_id())))?;
            let handle = client_endpoint.endpoint.handle;
            let direction = client_endpoint.endpoint.direction;

            let endpoint = self.read_and_update_endpoint(&handle, direction).await?;

            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(endpoint.ase_id, endpoint);
        }

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

    /// Performs the Configure Codec operation on one or more ASEs.
    ///
    /// This method sends the Configure Codec request to the remote server,
    /// waits for control point notifications for all involved ASEs, and
    /// verifies that the successfully configured ASEs have transitioned to
    /// the `CodecConfigured` state.
    ///
    /// # Arguments
    /// * `codec_configurations` - A vector of `CodecConfiguration` structs
    ///   containing the parameters for each ASE to be configured.
    ///
    /// # Returns
    /// On success, returns a tuple containing:
    /// * A `HashMap` mapping each successfully configured `AseId` to its
    ///   supported `QosParameters` published by the server.
    /// * A `Vec` containing the `ResponseCode` for any ASEs where the
    ///   configuration failed.
    pub async fn configure_codec(
        &mut self,
        codec_configurations: Vec<CodecConfiguration>,
    ) -> Result<AseControlOperationOutcome, Error> {
        let pending_ases: HashSet<AseId> = codec_configurations.iter().map(|c| c.ase_id).collect();
        self.verify_ase_ids(pending_ases.iter().cloned())?;

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

        self.perform_and_verify_operation(op, pending_ases).await
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use bt_common::core::CodecId;
    use bt_gatt::test_utils::{FakePeerService, FakeTypes};
    use bt_gatt::types::{AttributePermissions, 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: CharacteristicProperty::Write
                    | CharacteristicProperty::WriteWithoutResponse
                    | CharacteristicProperty::Notify,
                permissions: AttributePermissions::default(),
                descriptors: vec![],
            },
            vec![],
        );
        // Add Sink ASE
        service.add_characteristic(
            Characteristic {
                handle: SINK_ASE_HANDLE,
                uuid: SINK_ASE_UUID,
                properties: CharacteristicProperty::Read | CharacteristicProperty::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: CharacteristicProperty::Read | CharacteristicProperty::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: CharacteristicProperty::Read | CharacteristicProperty::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,
                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,
                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,
                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.add_characteristic(
            Characteristic {
                handle: SINK_ASE_HANDLE,
                uuid: SINK_ASE_UUID,
                properties: CharacteristicProperty::Read | CharacteristicProperty::Notify,
                permissions: AttributePermissions::default(),
                descriptors: vec![],
            },
            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,
            ],
        );

        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::Internal(ref s) if s.contains("Server rejected operation") && s.contains("InvalidLength")
        ));
    }
}
