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

//! Implements the Broadcast Audio Scan Service (BASS) server role.

use bt_bap::types::BroadcastCode;
use bt_common::packet_encoding::{Decodable, Encodable};
use bt_common::PeerId;
use bt_gatt::server::{
    LocalService, ReadResponder, Server as _, ServiceDefinition, ServiceEvent, ServiceId,
    WriteResponder,
};
use bt_gatt::types::{
    AttributePermissions, CharacteristicProperties, CharacteristicProperty, GattError, Handle,
    SecurityLevels, ServiceKind,
};
use bt_gatt::Characteristic;
use futures::stream::Stream;
use futures::Future;
use log::warn;
use pin_project::pin_project;
use std::collections::{BTreeMap, HashMap};
use std::num::NonZeroU8;
use std::task::{Poll, Waker};

use crate::types::*;

pub mod error;
use error::Error;

/// Service identifier assigned to the published BASS GATT service instance.
const BASS_SERVICE_ID: ServiceId = ServiceId::new(1);

/// Handle assigned to the Broadcast Audio Scan Control Point characteristic.
const CONTROL_POINT_HANDLE: Handle = Handle(1);

/// Maximum number of Broadcast Receive State characteristics that can be hosted
/// by the server. See BASS v1.0 Section 3.2.1.
const MAX_RECEIVE_STATES: usize = 255;

/// Internal representation of a Broadcast Receive State characteristic slot.
/// See BASS v1.0 Section 3.2.
#[derive(Debug)]
struct PublishedReceiveStateCharacteristic {
    /// Handle assigned to this GATT characteristic.
    handle: Handle,
    /// Current Broadcast Receive State value.
    state: BroadcastReceiveState,
}

/// A pending GATT notification to be dispatched following a state modification.
#[derive(Debug, PartialEq, Eq)]
struct PendingNotification {
    /// Handle of the characteristic to notify.
    handle: Handle,
    /// Encoded GATT characteristic value.
    value: Vec<u8>,
}

/// A parsed request to write to the Control Point characteristic.
struct ControlPointWriteResult {
    /// The decoded event associated with this request.
    event: ServerEvent,
    /// An optional notification to be sent to GATT peers.
    notification: Option<PendingNotification>,
}

/// Internal publication state lifecycle of the BASS GATT service.
#[pin_project(project = LocalServiceProj)]
enum LocalServiceState<T: bt_gatt::ServerTypes> {
    /// Service definition has not been registered in the GATT database.
    NotPublished {
        waker: Option<Waker>,
    },
    /// Service registration is in progress.
    Preparing {
        #[pin]
        fut: T::LocalServiceFut,
    },
    /// Service registration is complete and active in the GATT database.
    Published {
        service: T::LocalService,
        #[pin]
        events: T::ServiceEventStream,
    },
    Terminated,
}

impl<T: bt_gatt::ServerTypes> Default for LocalServiceState<T> {
    fn default() -> Self {
        Self::NotPublished { waker: None }
    }
}

impl<T: bt_gatt::ServerTypes> LocalServiceState<T> {
    fn is_published(&self) -> bool {
        matches!(self, LocalServiceState::Published { .. })
    }

    fn service(&self) -> Option<&T::LocalService> {
        match self {
            Self::Published { service, .. } => Some(service),
            _ => None,
        }
    }

    fn notify(&self, notification: &PendingNotification) {
        let Some(service) = self.service() else {
            warn!("Attempted to notify GATT peers on an unpublished service");
            return;
        };
        service.notify(&notification.handle, &notification.value, &[]);
    }
}

impl<T: bt_gatt::ServerTypes> Stream for LocalServiceState<T> {
    type Item = Result<bt_gatt::server::ServiceEvent<T>, Error>;

    fn poll_next(
        mut self: std::pin::Pin<&mut Self>,
        cx: &mut std::task::Context<'_>,
    ) -> Poll<Option<Self::Item>> {
        loop {
            match self.as_mut().project() {
                LocalServiceProj::Terminated => return Poll::Ready(None),
                LocalServiceProj::NotPublished { waker } => {
                    *waker = Some(cx.waker().clone());
                    return Poll::Pending;
                }
                LocalServiceProj::Preparing { fut } => {
                    let service_result = futures::ready!(fut.poll(cx));
                    let Ok(service) = service_result else {
                        self.as_mut().set(LocalServiceState::NotPublished { waker: None });
                        return Poll::Ready(Some(Err(Error::Gatt(service_result.err().unwrap()))));
                    };
                    let events = service.publish();
                    self.as_mut().set(LocalServiceState::Published { service, events });
                }
                LocalServiceProj::Published { service: _, events } => {
                    return match futures::ready!(events.poll_next(cx)) {
                        Some(Ok(event)) => Poll::Ready(Some(Ok(event))),
                        Some(Err(e)) => {
                            self.as_mut().set(LocalServiceState::Terminated);
                            Poll::Ready(Some(Err(Error::Gatt(e))))
                        }
                        None => {
                            self.as_mut().set(LocalServiceState::Terminated);
                            Poll::Ready(None)
                        }
                    };
                }
            }
        }
    }
}

/// Builder for constructing a BASS GATT [`Server`].
#[derive(Default)]
pub struct ServerBuilder {
    /// Staged Broadcast Receive State characteristics.
    /// There must be at least one such staged characteristic.
    receive_states: Vec<BroadcastReceiveState>,
}

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

    /// Adds a Broadcast Receive State characteristic slot to the builder.
    pub fn add_receive_state_characteristic(mut self, state: BroadcastReceiveState) -> Self {
        self.receive_states.push(state);
        self
    }

    /// Constructs the Broadcast Audio Scan Control Point characteristic.
    /// Defined in BASS v1.0 Section 3.1.
    fn build_control_point() -> Characteristic {
        let cp_properties: CharacteristicProperties =
            (&[CharacteristicProperty::Write, CharacteristicProperty::WriteWithoutResponse]).into();
        Characteristic {
            handle: CONTROL_POINT_HANDLE,
            uuid: BROADCAST_AUDIO_SCAN_CONTROL_POINT_UUID,
            properties: cp_properties,
            permissions: AttributePermissions::with_levels(
                &cp_properties,
                &SecurityLevels::encryption_required(),
            ),
            descriptors: Vec::new(),
        }
    }

    /// Constructs the Broadcast Receive State characteristic.
    /// Defined in BASS v1.0 Section 3.2.
    fn build_receive_state(handle: Handle) -> Characteristic {
        let properties = CharacteristicProperties::READ_NOTIFY;
        Characteristic {
            handle,
            uuid: BROADCAST_RECEIVE_STATE_UUID,
            properties,
            permissions: AttributePermissions::with_levels(
                &properties,
                &SecurityLevels::encryption_required(),
            ),
            descriptors: Vec::new(),
        }
    }

    /// Builds a [`Server`] instance after verifying required service
    /// characteristics.
    pub fn build<T: bt_gatt::ServerTypes>(self) -> Result<Server<T>, Error> {
        // Per BASS v1.0 Section 3.2, there must be [1,255] Broadcast Receive
        // State characteristics.
        if self.receive_states.is_empty() {
            return Err(Error::MissingReceiveState);
        }
        if self.receive_states.len() > MAX_RECEIVE_STATES {
            return Err(Error::ExceedsMaxReceiveStates);
        }

        let mut service_def = ServiceDefinition::new(
            BASS_SERVICE_ID,
            BROADCAST_AUDIO_SCAN_SERVICE_UUID,
            ServiceKind::Primary,
        );

        let _ = service_def.add_characteristic(Self::build_control_point());

        // Broadcast Receive State characteristics (Read, Notify; Encryption
        // Required). Handle(1) is allocated to the Control Point
        // Characteristic.
        const FIRST_RECEIVE_STATE_HANDLE: Handle = Handle(2);
        let num_receive_states = self.receive_states.len();
        let mut state = ServerState::new(num_receive_states);

        for (i, mut receive_state) in self.receive_states.into_iter().enumerate() {
            let handle = Handle(FIRST_RECEIVE_STATE_HANDLE.0 + i as u64);
            let _ = service_def.add_characteristic(Self::build_receive_state(handle));

            if let BroadcastReceiveState::NonEmpty(ref mut r) = receive_state {
                r.source_id = state
                    .allocate_source_id(handle)
                    .map_err(|e| Error::Gatt(bt_gatt::types::Error::Gatt(e)))?;
            }

            state.receive_state_characteristics.insert(
                handle,
                PublishedReceiveStateCharacteristic { handle, state: receive_state },
            );
        }

        Ok(Server { service_def, local_service: Default::default(), state })
    }
}

/// Events emitted by the [`Server`] when a remote GATT client writes to the
/// Control Point.
#[derive(Debug, PartialEq)]
pub enum ServerEvent {
    /// A client requested a change in remote scanning state.
    RemoteScanState { peer_id: PeerId, is_scanning: bool },
    /// A client requested adding a new Broadcast Source.
    AddSource { peer_id: PeerId, source_id: SourceId, operation: AddSourceOperation },
    /// A client requested modifying an existing Broadcast Source.
    ModifySource { peer_id: PeerId, source_id: SourceId, operation: ModifySourceOperation },
    /// A client provided a Broadcast Code for an encrypted Broadcast Source.
    SetBroadcastCode { peer_id: PeerId, source_id: SourceId, broadcast_code: BroadcastCode },
    /// A client requested removing a Broadcast Source.
    RemoveSource { peer_id: PeerId, source_id: SourceId },
}

impl ServerEvent {
    /// Attempts to decode a raw control point write request into a
    /// [`ServerEvent`].
    fn decode(peer_id: PeerId, val_bytes: &[u8]) -> Result<Self, GattError> {
        if val_bytes.is_empty() {
            return Err(GattError::WriteRequestRejected);
        }

        let raw_opcode = val_bytes[0];
        let Ok(opcode) = ControlPointOpcode::try_from(raw_opcode) else {
            return Err(ERROR_OPCODE_NOT_SUPPORTED);
        };

        match opcode {
            ControlPointOpcode::RemoteScanStopped => {
                let _ = decode_control_point_op::<RemoteScanStoppedOperation>(val_bytes)?;
                Ok(ServerEvent::RemoteScanState { peer_id, is_scanning: false })
            }
            ControlPointOpcode::RemoteScanStarted => {
                let _ = decode_control_point_op::<RemoteScanStartedOperation>(val_bytes)?;
                Ok(ServerEvent::RemoteScanState { peer_id, is_scanning: true })
            }
            ControlPointOpcode::AddSource => {
                let operation = decode_control_point_op::<AddSourceOperation>(val_bytes)?;
                // `source_id` will be assigned internally by the Server.
                Ok(ServerEvent::AddSource { peer_id, source_id: 0, operation })
            }
            ControlPointOpcode::ModifySource => {
                let operation = decode_control_point_op::<ModifySourceOperation>(val_bytes)?;
                Ok(ServerEvent::ModifySource { peer_id, source_id: operation.source_id, operation })
            }
            ControlPointOpcode::SetBroadcastCode => {
                let operation = decode_control_point_op::<SetBroadcastCodeOperation>(val_bytes)?;
                Ok(ServerEvent::SetBroadcastCode {
                    peer_id,
                    source_id: operation.source_id,
                    broadcast_code: operation.broadcast_code,
                })
            }
            ControlPointOpcode::RemoveSource => {
                let operation = decode_control_point_op::<RemoveSourceOperation>(val_bytes)?;
                Ok(ServerEvent::RemoveSource { peer_id, source_id: operation.0 })
            }
        }
    }
}

/// Attempts to decode a control point operation payload.
fn decode_control_point_op<O: Decodable>(val_bytes: &[u8]) -> Result<O, GattError> {
    let (Ok(op), consumed) = O::decode(val_bytes) else {
        return Err(GattError::WriteRequestRejected);
    };
    if consumed != val_bytes.len() {
        return Err(GattError::WriteRequestRejected);
    }
    Ok(op)
}

/// Internal state of the BASS GATT Server.
#[derive(Debug)]
struct ServerState {
    /// Broadcast Receive State characteristics identified by the assigned
    /// GATT handle.
    receive_state_characteristics: BTreeMap<Handle, PublishedReceiveStateCharacteristic>,
    /// Unique IDs tracking each assigned GATT Handle.
    source_id_to_handle: HashMap<SourceId, Handle>,
    /// Next available Source ID to be assigned to an empty Receive State
    /// characteristic.
    /// Must be in [1, 255]. See BASS spec v1.0 Section 3.2.1.
    next_source_id: NonZeroU8,
}

impl ServerState {
    fn new(capacity: usize) -> Self {
        Self {
            receive_state_characteristics: BTreeMap::new(),
            source_id_to_handle: HashMap::with_capacity(capacity),
            next_source_id: NonZeroU8::MIN,
        }
    }

    /// Allocates the next available, unused [`SourceId`] and maps it to
    /// `handle`.
    ///
    /// Returns the assigned ID on success.
    /// Returns `GattError::InsufficientResources` if all 255 Source IDs
    /// are currently in use.
    fn allocate_source_id(&mut self, handle: Handle) -> Result<SourceId, GattError> {
        // Upper bound on the maximum number of unique SourceIDs (u8 max).
        for _ in 0..NonZeroU8::MAX.get() {
            let id = self.next_source_id.get();
            self.next_source_id = self.next_source_id.checked_add(1).unwrap_or(NonZeroU8::MIN);
            if !self.source_id_to_handle.contains_key(&id) {
                self.source_id_to_handle.insert(id, handle);
                return Ok(id);
            }
        }
        Err(GattError::InsufficientResources)
    }

    /// Allocates a new SourceId for the next available Receive State
    /// characteristic entry.
    ///
    /// Returns the assigned [`Handle`] and [`SourceId`] on success.
    fn allocate_receive_state_chrc(&mut self) -> Result<(Handle, SourceId), GattError> {
        let handle = self
            .receive_state_characteristics
            .values()
            .find(|c| c.state.is_empty())
            .map(|c| c.handle)
            .ok_or(GattError::InsufficientResources)?;

        let source_id = self.allocate_source_id(handle)?;
        Ok((handle, source_id))
    }

    /// Handles a read request for a characteristic on the BASS server.
    fn handle_read(&self, handle: Handle, offset: usize, responder: impl ReadResponder) {
        // Only the Broadcast Receive State characteristics can be read.
        // See BASS spec v1.0 Section 3.3.2.
        if handle == CONTROL_POINT_HANDLE {
            responder.error(GattError::ReadNotPermitted);
            return;
        }

        let Some(chrc) = self.receive_state_characteristics.get(&handle) else {
            responder.error(GattError::InvalidHandle);
            return;
        };

        let len = chrc.state.encoded_len();
        if offset > len {
            responder.error(GattError::InvalidOffset);
            return;
        }

        let mut buf = vec![0u8; len];
        match chrc.state.encode(&mut buf) {
            Ok(_) => responder.respond(&buf[offset..]),
            Err(_) => responder.error(GattError::UnlikelyError),
        }
    }

    /// Handles a write request for a characteristic on the BASS server.
    fn handle_write(
        &mut self,
        peer_id: PeerId,
        handle: Handle,
        value: &[u8],
    ) -> Result<ControlPointWriteResult, GattError> {
        // Only the Broadcast Audio Scan Control Point characteristic can be
        // written to by a client. See BASS v1.0 Section 3.3.
        if handle != CONTROL_POINT_HANDLE {
            return Err(GattError::WriteNotPermitted);
        }

        self.handle_control_point_write(peer_id, value)
    }

    /// Returns true if the specified `source_id` is assigned to a non-empty
    /// Receive State characteristic.
    fn is_valid_source_id(&self, source_id: SourceId) -> bool {
        self.source_id_to_handle
            .get(&source_id)
            .and_then(|h| self.receive_state_characteristics.get(h))
            .map_or(false, |s| !s.state.is_empty())
    }

    fn handle_control_point_write(
        &mut self,
        peer_id: PeerId,
        val_bytes: &[u8],
    ) -> Result<ControlPointWriteResult, GattError> {
        let mut event = ServerEvent::decode(peer_id, val_bytes)?;
        let notification = match &mut event {
            ServerEvent::RemoteScanState { .. } => None,
            ServerEvent::AddSource { source_id, operation, .. } => {
                let (notification, assigned_source_id) = self.handle_add_source_write(operation)?;
                *source_id = assigned_source_id;
                Some(notification)
            }
            ServerEvent::ModifySource { operation, .. } => {
                let notification = self.handle_modify_source_write(operation)?;
                Some(notification)
            }
            ServerEvent::SetBroadcastCode { source_id, .. } => {
                if !self.is_valid_source_id(*source_id) {
                    return Err(ERROR_INVALID_SOURCE_ID);
                }
                None
            }
            ServerEvent::RemoveSource { source_id, .. } => {
                let notification = self.handle_remove_source_write(*source_id)?;
                Some(notification)
            }
        };

        Ok(ControlPointWriteResult { event, notification })
    }

    fn handle_add_source_write(
        &mut self,
        operation: &AddSourceOperation,
    ) -> Result<(PendingNotification, SourceId), GattError> {
        let (handle, source_id) = self.allocate_receive_state_chrc()?;
        let chrc =
            self.receive_state_characteristics.get_mut(&handle).expect("just checked existence");
        let pa_sync_state = PaSyncState::from_pa_sync(operation.pa_sync);
        let subgroups = operation
            .subgroups
            .iter()
            .map(|s| BigSubgroup::new(Some(s.bis_sync.clone())).with_metadata(s.metadata.clone()))
            .collect();

        let initial_state = ReceiveState::new(
            source_id,
            operation.advertiser_address_type,
            operation.advertiser_address,
            operation.advertising_sid,
            operation.broadcast_id,
            pa_sync_state,
            EncryptionStatus::NotEncrypted,
            subgroups,
        );

        let new_state = BroadcastReceiveState::NonEmpty(initial_state);
        let mut value = vec![0u8; new_state.encoded_len()];
        new_state.encode(&mut value).map_err(|_| GattError::UnlikelyError)?;

        chrc.state = new_state;
        Ok((PendingNotification { handle, value }, source_id))
    }

    fn handle_modify_source_write(
        &mut self,
        operation: &ModifySourceOperation,
    ) -> Result<PendingNotification, GattError> {
        let Some(handle) = self.source_id_to_handle.get(&operation.source_id).copied() else {
            return Err(ERROR_INVALID_SOURCE_ID);
        };
        let Some(chrc) = self.receive_state_characteristics.get_mut(&handle) else {
            return Err(ERROR_INVALID_SOURCE_ID);
        };
        let BroadcastReceiveState::NonEmpty(ref state) = chrc.state else {
            return Err(ERROR_INVALID_SOURCE_ID);
        };

        let subgroups = operation
            .subgroups
            .iter()
            .map(|s| BigSubgroup::new(Some(s.bis_sync.clone())).with_metadata(s.metadata.clone()))
            .collect();

        let mut modified_state = state.clone();
        modified_state.subgroups = subgroups;
        modified_state.pa_sync_state = PaSyncState::from_pa_sync(operation.pa_sync);

        let new_state = BroadcastReceiveState::NonEmpty(modified_state);
        let mut value = vec![0u8; new_state.encoded_len()];
        new_state.encode(&mut value).map_err(|_| GattError::UnlikelyError)?;

        chrc.state = new_state;
        Ok(PendingNotification { handle, value })
    }

    fn handle_remove_source_write(
        &mut self,
        source_id: SourceId,
    ) -> Result<PendingNotification, GattError> {
        let Some(handle) = self.source_id_to_handle.get(&source_id).copied() else {
            return Err(ERROR_INVALID_SOURCE_ID);
        };
        let Some(chrc) = self.receive_state_characteristics.get_mut(&handle) else {
            return Err(ERROR_INVALID_SOURCE_ID);
        };
        if chrc.state.is_empty() {
            return Err(ERROR_INVALID_SOURCE_ID);
        }

        let _ = self.source_id_to_handle.remove(&source_id);
        chrc.state = BroadcastReceiveState::Empty;

        let mut value = vec![0u8; chrc.state.encoded_len()];
        chrc.state.encode(&mut value).map_err(|_| GattError::UnlikelyError)?;

        Ok(PendingNotification { handle, value })
    }
}

/// The BASS GATT Server implementation.
///
/// Manages the Control Point characteristic and one or more Broadcast Receive
/// State characteristics.
#[pin_project]
pub struct Server<T: bt_gatt::ServerTypes> {
    service_def: ServiceDefinition,
    #[pin]
    local_service: LocalServiceState<T>,
    state: ServerState,
}

impl<T: bt_gatt::ServerTypes> Server<T> {
    /// Returns true if the server has successfully published the GATT service.
    pub fn is_published(&self) -> bool {
        self.local_service.is_published()
    }

    /// Publishes the service to the GATT database.
    pub fn publish(&mut self, server: T::Server) -> Result<(), Error> {
        if !matches!(self.local_service, LocalServiceState::NotPublished { .. }) {
            return Err(Error::AlreadyPublished);
        }

        let LocalServiceState::NotPublished { waker } = std::mem::replace(
            &mut self.local_service,
            LocalServiceState::Preparing { fut: server.prepare(self.service_def.clone()) },
        ) else {
            unreachable!();
        };

        if let Some(w) = waker {
            w.wake();
        }

        Ok(())
    }
    /// Adds a new [`ReceiveState`] to the next available characteristic slot
    /// and sends a GATT notification to all subscribed peers.
    ///
    /// Characteristic slots are allocated up-front when constructing the server
    /// via [`ServerBuilder`]. This method populates an available empty slot
    /// with `state` when initiated locally.
    ///
    /// Returns the assigned [`SourceId`] for the characteristic on success.
    /// Returns [`Error::ServerFull`] if all characteristic slots are occupied.
    pub fn add_receive_state(&mut self, mut state: ReceiveState) -> Result<SourceId, Error> {
        let (_handle, source_id) =
            self.state.allocate_receive_state_chrc().map_err(|_| Error::ServerFull)?;
        state.source_id = source_id;
        self.set_receive_state_and_notify(source_id, BroadcastReceiveState::NonEmpty(state))?;
        Ok(source_id)
    }

    /// Updates the existing [`BroadcastReceiveState`] characteristic with the
    /// provided `state` and sends a GATT notification to all subscribed peers.
    ///
    /// Returns [`Error::InvalidSourceId`] if there is no such characteristic.
    pub fn update_receive_state(&mut self, state: ReceiveState) -> Result<(), Error> {
        self.set_receive_state_and_notify(state.source_id(), BroadcastReceiveState::NonEmpty(state))
    }

    /// Clears the entry for the specified Broadcast Receive State
    /// characteristic and sends a GATT notification to all subscribed peers.
    ///
    /// Returns [`Error::InvalidSourceId`] if there is no such characteristic.
    pub fn clear_receive_state(&mut self, source_id: SourceId) -> Result<(), Error> {
        self.set_receive_state_and_notify(source_id, BroadcastReceiveState::Empty)
    }

    /// Updates the state for the specified Broadcast Receive Characteristic and
    /// sends a GATT notification to all subscribed peers.
    ///
    /// Returns [`Error::InvalidSourceId`] if there is no such characteristic.
    fn set_receive_state_and_notify(
        &mut self,
        source_id: SourceId,
        new_state: BroadcastReceiveState,
    ) -> Result<(), Error> {
        let handle = *self
            .state
            .source_id_to_handle
            .get(&source_id)
            .ok_or(Error::InvalidSourceId(source_id))?;

        let chrc = self
            .state
            .receive_state_characteristics
            .get_mut(&handle)
            .ok_or(Error::InvalidSourceId(source_id))?;

        let mut value = vec![0u8; new_state.encoded_len()];
        new_state.encode(&mut value)?;

        if new_state.is_empty() {
            self.state.source_id_to_handle.remove(&source_id);
        } else {
            self.state.source_id_to_handle.insert(source_id, handle);
        }

        chrc.state = new_state;

        self.local_service.notify(&PendingNotification { handle, value });

        Ok(())
    }
}

impl<T: bt_gatt::ServerTypes> Stream for Server<T> {
    type Item = Result<ServerEvent, Error>;

    fn poll_next(
        mut self: std::pin::Pin<&mut Self>,
        cx: &mut std::task::Context<'_>,
    ) -> Poll<Option<Self::Item>> {
        loop {
            let mut this = self.as_mut().project();
            let gatt_event = match futures::ready!(this.local_service.as_mut().poll_next(cx)) {
                Some(Ok(event)) => event,
                Some(Err(e)) => return Poll::Ready(Some(Err(e))),
                None => return Poll::Ready(None),
            };

            match gatt_event {
                ServiceEvent::Read { handle, offset, responder, .. } => {
                    this.state.handle_read(handle, offset as usize, responder);
                }
                ServiceEvent::Write { handle, peer_id, value, responder, .. } => {
                    let val_vec = value.to_owned();
                    match this.state.handle_write(peer_id, handle, &val_vec) {
                        Ok(result) => {
                            if let Some(notification) = result.notification {
                                this.local_service.notify(&notification);
                            }
                            responder.acknowledge();
                            return Poll::Ready(Some(Ok(result.event)));
                        }
                        Err(err) => {
                            responder.error(err);
                        }
                    }
                }
                _ => {
                    // TODO(b/534436439): Track CCC for Broadcast Receive State
                    // characteristics and `PeerInfo` if needed.
                }
            }
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use assert_matches::assert_matches;
    use bt_bap::types::BroadcastId;

    use bt_common::core::{Address, AddressType, AdvertisingSetId, PeriodicAdvertisingInterval};
    use bt_common::generic_audio::metadata_ltv::Metadata;
    use bt_gatt::test_utils::{FakeServer, FakeServerEvent, FakeTypes};
    use bt_gatt::types::GattError;
    use futures::task::Context;
    use futures::FutureExt;
    use futures::StreamExt;
    use std::task::Poll;

    use crate::types::{BigSubgroup, EncryptionStatus, PaSync, PaSyncState, ReceiveState};

    fn make_test_inner_receive_state(source_id: SourceId) -> ReceiveState {
        ReceiveState::new(
            source_id,
            AddressType::Public,
            Address::new([0x01, 0x02, 0x03, 0x04, 0x05, 0x06]),
            AdvertisingSetId::try_from(1).unwrap(),
            BroadcastId::try_from(0x123456).unwrap(),
            PaSyncState::NotSynced,
            EncryptionStatus::NotEncrypted,
            vec![],
        )
    }

    fn make_test_receive_state(source_id: SourceId) -> BroadcastReceiveState {
        BroadcastReceiveState::NonEmpty(make_test_inner_receive_state(source_id))
    }

    #[test]
    fn empty_builder_fails() {
        let builder = ServerBuilder::new();
        assert!(matches!(builder.build::<FakeTypes>(), Err(Error::MissingReceiveState)));
    }

    #[test]
    fn too_many_receive_states_fails() {
        let mut builder = ServerBuilder::new();
        for _ in 0..=MAX_RECEIVE_STATES {
            builder = builder.add_receive_state_characteristic(BroadcastReceiveState::Empty);
        }
        assert!(matches!(builder.build::<FakeTypes>(), Err(Error::ExceedsMaxReceiveStates)));
    }

    fn setup_test_server(
        receive_states: Vec<BroadcastReceiveState>,
    ) -> (
        Server<FakeTypes>,
        FakeServer,
        futures::channel::mpsc::UnboundedReceiver<FakeServerEvent>,
        Context<'static>,
    ) {
        let mut noop_cx = Context::from_waker(futures::task::noop_waker_ref());
        let (fake_gatt_server, mut event_receiver) = FakeServer::new();
        let mut event_stream = event_receiver.next();

        let mut builder = ServerBuilder::new();
        for state in receive_states {
            builder = builder.add_receive_state_characteristic(state);
        }
        let mut server = builder.build::<FakeTypes>().expect("building server works");

        server.publish(fake_gatt_server.clone()).expect("publish ok");
        let _ = server.poll_next_unpin(&mut noop_cx);
        assert!(matches!(
            event_stream.poll_unpin(&mut noop_cx),
            Poll::Ready(Some(FakeServerEvent::Published { .. }))
        ));

        (server, fake_gatt_server, event_receiver, noop_cx)
    }

    #[test]
    fn publish_server() {
        let mut noop_cx = Context::from_waker(futures::task::noop_waker_ref());

        let mut server = ServerBuilder::new()
            .add_receive_state_characteristic(BroadcastReceiveState::Empty)
            .add_receive_state_characteristic(make_test_receive_state(2))
            .build::<FakeTypes>()
            .expect("building server works");

        assert!(!server.is_published());

        let (fake_gatt_server, mut event_receiver) = FakeServer::new();
        let mut event_stream = event_receiver.next();

        assert!(server.publish(fake_gatt_server.clone()).is_ok());
        assert!(server.publish(fake_gatt_server).is_err());

        // Polling stream completes publication preparation
        let _ = server.poll_next_unpin(&mut noop_cx);
        assert!(server.is_published());

        let Poll::Ready(Some(FakeServerEvent::Published { id, definition })) =
            event_stream.poll_unpin(&mut noop_cx)
        else {
            panic!("Expected published event");
        };

        assert_eq!(id, BASS_SERVICE_ID);
        assert_eq!(definition.uuid(), BROADCAST_AUDIO_SCAN_SERVICE_UUID);
        assert_eq!(definition.characteristics().count(), 3);
    }

    #[test]
    fn read_receive_state() {
        let (mut server, fake_gatt_server, mut event_receiver, mut noop_cx) =
            setup_test_server(vec![BroadcastReceiveState::Empty, make_test_receive_state(2)]);
        let mut event_stream = event_receiver.next();
        assert!(server.is_published());

        // 1. Read empty Receive State slot (Handle 2)
        fake_gatt_server.incoming_read(PeerId(1), BASS_SERVICE_ID, Handle(2), 0);
        let _ = server.poll_next_unpin(&mut noop_cx);
        let Poll::Ready(Some(FakeServerEvent::ReadResponded { handle, value, .. })) =
            event_stream.poll_unpin(&mut noop_cx)
        else {
            panic!("Expected ReadResponded event");
        };
        assert_eq!(handle, Handle(2));
        assert_eq!(value.unwrap(), vec![]);

        // 2. Read populated Receive State slot (Handle 3)
        fake_gatt_server.incoming_read(PeerId(1), BASS_SERVICE_ID, Handle(3), 0);
        let _ = server.poll_next_unpin(&mut noop_cx);
        let Poll::Ready(Some(FakeServerEvent::ReadResponded { handle, value, .. })) =
            event_stream.poll_unpin(&mut noop_cx)
        else {
            panic!("Expected ReadResponded event");
        };
        assert_eq!(handle, Handle(3));
        assert!(!value.unwrap().is_empty());

        // 3. Read unknown handle (Handle 99)
        fake_gatt_server.incoming_read(PeerId(1), BASS_SERVICE_ID, Handle(99), 0);
        let _ = server.poll_next_unpin(&mut noop_cx);
        let Poll::Ready(Some(FakeServerEvent::ReadResponded { handle, value, .. })) =
            event_stream.poll_unpin(&mut noop_cx)
        else {
            panic!("Expected ReadResponded event");
        };
        assert_eq!(handle, Handle(99));
        assert!(matches!(
            value.unwrap_err(),
            bt_gatt::types::Error::Gatt(GattError::InvalidHandle)
        ));
    }

    #[test]
    fn control_point_remote_scan_state_changed() {
        let (mut server, fake_gatt_server, mut event_receiver, mut noop_cx) =
            setup_test_server(vec![BroadcastReceiveState::Empty]);
        let mut event_stream = event_receiver.next();

        // Simulate RemoteScanStarted request
        let raw_cmd = vec![ControlPointOpcode::RemoteScanStarted as u8];
        fake_gatt_server.incoming_write(PeerId(1), BASS_SERVICE_ID, Handle(1), 0, raw_cmd);

        let Poll::Ready(Some(Ok(event))) = server.poll_next_unpin(&mut noop_cx) else {
            panic!("Expected ServerEvent");
        };
        assert_eq!(event, ServerEvent::RemoteScanState { peer_id: PeerId(1), is_scanning: true });

        let Poll::Ready(Some(FakeServerEvent::WriteResponded { handle, value, .. })) =
            event_stream.poll_unpin(&mut noop_cx)
        else {
            panic!("Expected WriteResponded event");
        };
        assert_eq!(handle, Handle(1));
        assert!(value.is_ok());

        // Simulate RemoteScanStopped request
        let raw_cmd = vec![ControlPointOpcode::RemoteScanStopped as u8];
        fake_gatt_server.incoming_write(PeerId(1), BASS_SERVICE_ID, Handle(1), 0, raw_cmd);

        let Poll::Ready(Some(Ok(event))) = server.poll_next_unpin(&mut noop_cx) else {
            panic!("Expected ServerEvent");
        };
        assert_eq!(event, ServerEvent::RemoteScanState { peer_id: PeerId(1), is_scanning: false });

        let Poll::Ready(Some(FakeServerEvent::WriteResponded { handle, value, .. })) =
            event_stream.poll_unpin(&mut noop_cx)
        else {
            panic!("Expected WriteResponded event");
        };
        assert_eq!(handle, Handle(1));
        assert!(value.is_ok());
    }

    #[test]
    fn control_point_invalid_opcode_fails() {
        let (mut server, fake_gatt_server, mut event_receiver, mut noop_cx) =
            setup_test_server(vec![BroadcastReceiveState::Empty]);
        let mut event_stream = event_receiver.next();

        // Simulate invalid opcode request
        fake_gatt_server.incoming_write(PeerId(1), BASS_SERVICE_ID, Handle(1), 0, vec![0xFF]);

        let _ = server.poll_next_unpin(&mut noop_cx);

        let Poll::Ready(Some(FakeServerEvent::WriteResponded { handle, value, .. })) =
            event_stream.poll_unpin(&mut noop_cx)
        else {
            panic!("Expected WriteResponded event");
        };
        assert_eq!(handle, Handle(1));
        assert!(matches!(
            value.unwrap_err(),
            bt_gatt::types::Error::Gatt(GattError::ApplicationError80)
        ));
    }

    #[test]
    fn control_point_unallocated_source_id_fails() {
        let (mut server, fake_gatt_server, mut event_receiver, mut noop_cx) =
            setup_test_server(vec![BroadcastReceiveState::Empty]);
        let mut event_stream = event_receiver.next();

        // Operation targeting SourceId = 1 (slot exists, but is empty)
        let modify_op = ModifySourceOperation::new(
            1,
            PaSync::DoNotSync,
            PeriodicAdvertisingInterval(0xFFFF),
            vec![],
        );
        let mut raw_bytes = vec![0u8; modify_op.encoded_len()];
        modify_op.encode(&mut raw_bytes).expect("encode ok");

        fake_gatt_server.incoming_write(PeerId(1), BASS_SERVICE_ID, Handle(1), 0, raw_bytes);

        let _ = server.poll_next_unpin(&mut noop_cx);

        let Poll::Ready(Some(FakeServerEvent::WriteResponded { handle, value, .. })) =
            event_stream.poll_unpin(&mut noop_cx)
        else {
            panic!("Expected WriteResponded event");
        };
        assert_eq!(handle, Handle(1));
        assert!(matches!(
            value.unwrap_err(),
            bt_gatt::types::Error::Gatt(GattError::ApplicationError81)
        ));
    }

    #[test]
    fn control_point_nonexistent_source_id_fails() {
        let (mut server, fake_gatt_server, mut event_receiver, mut noop_cx) =
            setup_test_server(vec![BroadcastReceiveState::Empty]);
        let mut event_stream = event_receiver.next();

        // ModifySource operation targeting SourceId = 99 (does not exist)
        let modify_op = ModifySourceOperation::new(
            99,
            PaSync::DoNotSync,
            PeriodicAdvertisingInterval(0xFFFF),
            vec![],
        );
        let mut raw_bytes = vec![0u8; modify_op.encoded_len()];
        modify_op.encode(&mut raw_bytes).expect("encode ok");

        fake_gatt_server.incoming_write(PeerId(1), BASS_SERVICE_ID, Handle(1), 0, raw_bytes);

        let _ = server.poll_next_unpin(&mut noop_cx);

        let Poll::Ready(Some(FakeServerEvent::WriteResponded { handle, value, .. })) =
            event_stream.poll_unpin(&mut noop_cx)
        else {
            panic!("Expected WriteResponded event");
        };
        assert_eq!(handle, Handle(1));
        assert!(matches!(
            value.unwrap_err(),
            bt_gatt::types::Error::Gatt(GattError::ApplicationError81)
        ));
    }

    #[test]
    fn control_point_extra_bytes_fails() {
        let (mut server, fake_gatt_server, mut event_receiver, mut noop_cx) =
            setup_test_server(vec![BroadcastReceiveState::Empty]);
        let mut event_stream = event_receiver.next();

        // RemoteScanStarted opcode (1 byte) with extra trailing byte (0xFF)
        let raw_cmd = vec![ControlPointOpcode::RemoteScanStarted as u8, 0xFF];
        fake_gatt_server.incoming_write(PeerId(1), BASS_SERVICE_ID, Handle(1), 0, raw_cmd);

        let _ = server.poll_next_unpin(&mut noop_cx);

        let Poll::Ready(Some(FakeServerEvent::WriteResponded { handle, value, .. })) =
            event_stream.poll_unpin(&mut noop_cx)
        else {
            panic!("Expected WriteResponded event");
        };
        assert_eq!(handle, Handle(1));
        assert!(matches!(
            value.unwrap_err(),
            bt_gatt::types::Error::Gatt(GattError::WriteRequestRejected)
        ));
    }

    #[test]
    fn control_point_add_source_success() {
        let (mut server, fake_gatt_server, mut event_receiver, mut noop_cx) =
            setup_test_server(vec![BroadcastReceiveState::Empty]);
        let mut event_stream = event_receiver.next();

        fake_gatt_server.incoming_client_configuration(
            PeerId(1),
            BASS_SERVICE_ID,
            Handle(2),
            bt_gatt::server::NotificationType::Notify,
        );
        let _ = server.poll_next_unpin(&mut noop_cx);

        // 1. Remote client writes AddSource to Control Point (Handle 1)
        let add_op = AddSourceOperation::new(
            AddressType::Public,
            Address::new([1, 2, 3, 4, 5, 6]),
            AdvertisingSetId::try_from(1).unwrap(),
            BroadcastId::try_from(0x123456).unwrap(),
            PaSync::SyncPastAvailable,
            PeriodicAdvertisingInterval(0x0010),
            vec![],
        );
        let mut raw_bytes = vec![0u8; add_op.encoded_len()];
        add_op.encode(&mut raw_bytes).expect("encode ok");

        fake_gatt_server.incoming_write(PeerId(1), BASS_SERVICE_ID, Handle(1), 0, raw_bytes);

        // Server stream emits AddSource event
        let Poll::Ready(Some(Ok(event))) = server.poll_next_unpin(&mut noop_cx) else {
            panic!("Expected ServerEvent");
        };
        let ServerEvent::AddSource { peer_id, source_id, operation } = event else {
            panic!("Expected AddSource event, got {event:?}");
        };
        assert_eq!(peer_id, PeerId(1));
        assert_eq!(source_id, 1);
        assert_eq!(operation, add_op);

        // First notification: Initial minimal state created upon Control Point
        // write
        let Poll::Ready(Some(FakeServerEvent::Notified { handle, value, .. })) =
            event_stream.poll_unpin(&mut noop_cx)
        else {
            panic!("Expected first Notified event");
        };
        assert_eq!(handle, Handle(2));
        let (first_notification_state, _) = BroadcastReceiveState::decode(&value);
        let BroadcastReceiveState::NonEmpty(initial_state) =
            first_notification_state.expect("valid decode")
        else {
            panic!("Expected NonEmpty state in first notification");
        };
        assert_eq!(initial_state.source_id, 1);
        assert_eq!(initial_state.pa_sync_state, PaSyncState::SyncInfoRequest);

        // Write response is sent to client
        let Poll::Ready(Some(FakeServerEvent::WriteResponded { handle, value, .. })) =
            event_stream.poll_unpin(&mut noop_cx)
        else {
            panic!("Expected WriteResponded event");
        };
        assert_eq!(handle, Handle(1));
        assert!(value.is_ok());

        // 2. Upper layer client processes the event, establishes PA sync, and
        //    updates state
        let mut updated_state = initial_state;
        updated_state.pa_sync_state = PaSyncState::Synced;
        assert!(server.update_receive_state(updated_state).is_ok());

        // Second notification: Upper layer client calls public API method
        // (update_receive_state)
        let Poll::Ready(Some(FakeServerEvent::Notified { handle, value, peers, .. })) =
            event_stream.poll_unpin(&mut noop_cx)
        else {
            panic!("Expected second Notified event");
        };
        assert_eq!(handle, Handle(2));
        assert_eq!(peers, vec![PeerId(1)]);
        let (second_notification_state, _) = BroadcastReceiveState::decode(&value);
        let BroadcastReceiveState::NonEmpty(final_state) =
            second_notification_state.expect("valid decode")
        else {
            panic!("Expected NonEmpty state in second notification");
        };
        assert_eq!(final_state.source_id, 1);
        assert_eq!(final_state.pa_sync_state, PaSyncState::Synced);
    }

    #[test]
    fn control_point_modify_source_success() {
        let (mut server, fake_gatt_server, mut event_receiver, mut noop_cx) =
            setup_test_server(vec![make_test_receive_state(1)]);
        let mut event_stream = event_receiver.next();

        fake_gatt_server.incoming_client_configuration(
            PeerId(1),
            BASS_SERVICE_ID,
            Handle(2),
            bt_gatt::server::NotificationType::Notify,
        );
        let _ = server.poll_next_unpin(&mut noop_cx);

        // 1. Remote client writes ModifySource to Control Point (Handle 1)
        let modify_op = ModifySourceOperation::new(
            1,
            PaSync::DoNotSync,
            PeriodicAdvertisingInterval(0xFFFF),
            vec![],
        );
        let mut raw_bytes = vec![0u8; modify_op.encoded_len()];
        modify_op.encode(&mut raw_bytes).expect("encode ok");

        fake_gatt_server.incoming_write(PeerId(1), BASS_SERVICE_ID, Handle(1), 0, raw_bytes);

        // Server stream emits ModifySource event
        let Poll::Ready(Some(Ok(event))) = server.poll_next_unpin(&mut noop_cx) else {
            panic!("Expected ServerEvent");
        };
        assert_eq!(
            event,
            ServerEvent::ModifySource { peer_id: PeerId(1), source_id: 1, operation: modify_op }
        );

        // First notification: State updated upon Control Point write
        let Poll::Ready(Some(FakeServerEvent::Notified { handle, value, .. })) =
            event_stream.poll_unpin(&mut noop_cx)
        else {
            panic!("Expected first Notified event");
        };
        assert_eq!(handle, Handle(2));
        let (first_state, _) = BroadcastReceiveState::decode(&value);
        let BroadcastReceiveState::NonEmpty(modified_state) = first_state.expect("valid decode")
        else {
            panic!("Expected NonEmpty state");
        };
        assert_eq!(modified_state.pa_sync_state, PaSyncState::NotSynced);

        let Poll::Ready(Some(FakeServerEvent::WriteResponded { handle, value, .. })) =
            event_stream.poll_unpin(&mut noop_cx)
        else {
            panic!("Expected WriteResponded event");
        };
        assert_eq!(handle, Handle(1));
        assert!(value.is_ok());

        // 2. Upper layer client processes the event and calls public API method
        //    (update_receive_state)
        let mut updated_state = modified_state;
        updated_state.pa_sync_state = PaSyncState::FailedToSync;
        assert!(server.update_receive_state(updated_state).is_ok());

        // Second notification: Upper layer client calls public API method
        let Poll::Ready(Some(FakeServerEvent::Notified { handle, value, peers, .. })) =
            event_stream.poll_unpin(&mut noop_cx)
        else {
            panic!("Expected second Notified event");
        };
        assert_eq!(handle, Handle(2));
        assert_eq!(peers, vec![PeerId(1)]);
        let (second_state, _) = BroadcastReceiveState::decode(&value);
        let BroadcastReceiveState::NonEmpty(final_state) = second_state.expect("valid decode")
        else {
            panic!("Expected NonEmpty state");
        };
        assert_eq!(final_state.pa_sync_state, PaSyncState::FailedToSync);
    }

    #[test]
    fn control_point_set_broadcast_code_success() {
        let (mut server, fake_gatt_server, mut event_receiver, mut noop_cx) =
            setup_test_server(vec![make_test_receive_state(1)]);
        let mut event_stream = event_receiver.next();

        let code = BroadcastCode::new([0xAB; 16]);
        let set_code_op = SetBroadcastCodeOperation::new(1, code);
        let mut raw_bytes = vec![0u8; set_code_op.encoded_len()];
        set_code_op.encode(&mut raw_bytes).expect("encode ok");

        fake_gatt_server.incoming_write(PeerId(1), BASS_SERVICE_ID, Handle(1), 0, raw_bytes);

        let Poll::Ready(Some(Ok(event))) = server.poll_next_unpin(&mut noop_cx) else {
            panic!("Expected ServerEvent");
        };
        assert_eq!(
            event,
            ServerEvent::SetBroadcastCode {
                peer_id: PeerId(1),
                source_id: 1,
                broadcast_code: code,
            }
        );

        let Poll::Ready(Some(FakeServerEvent::WriteResponded { handle, value, .. })) =
            event_stream.poll_unpin(&mut noop_cx)
        else {
            panic!("Expected WriteResponded event");
        };
        assert_eq!(handle, Handle(1));
        assert!(value.is_ok());
    }

    #[test]
    fn control_point_remove_source_success() {
        let (mut server, fake_gatt_server, mut event_receiver, mut noop_cx) =
            setup_test_server(vec![make_test_receive_state(1)]);
        let mut event_stream = event_receiver.next();

        fake_gatt_server.incoming_client_configuration(
            PeerId(1),
            BASS_SERVICE_ID,
            Handle(2),
            bt_gatt::server::NotificationType::Notify,
        );
        let _ = server.poll_next_unpin(&mut noop_cx);

        let remove_op = RemoveSourceOperation::new(1);
        let mut raw_bytes = vec![0u8; remove_op.encoded_len()];
        remove_op.encode(&mut raw_bytes).expect("encode ok");

        fake_gatt_server.incoming_write(PeerId(1), BASS_SERVICE_ID, Handle(1), 0, raw_bytes);

        let Poll::Ready(Some(Ok(event))) = server.poll_next_unpin(&mut noop_cx) else {
            panic!("Expected ServerEvent");
        };
        assert_eq!(event, ServerEvent::RemoveSource { peer_id: PeerId(1), source_id: 1 });

        let Poll::Ready(Some(FakeServerEvent::Notified { handle, value, .. })) =
            event_stream.poll_unpin(&mut noop_cx)
        else {
            panic!("Expected Notified event");
        };
        assert_eq!(handle, Handle(2));
        assert!(value.is_empty());

        let Poll::Ready(Some(FakeServerEvent::WriteResponded { handle, value, .. })) =
            event_stream.poll_unpin(&mut noop_cx)
        else {
            panic!("Expected WriteResponded event");
        };
        assert_eq!(handle, Handle(1));
        assert!(value.is_ok());
    }

    #[test]
    fn write_non_control_point_fails() {
        let (mut server, fake_gatt_server, mut event_receiver, mut noop_cx) =
            setup_test_server(vec![BroadcastReceiveState::Empty]);
        let mut event_stream = event_receiver.next();

        // Writing to BroadcastReceiveState characteristic handle (Handle 2)
        fake_gatt_server.incoming_write(PeerId(1), BASS_SERVICE_ID, Handle(2), 0, vec![0x01]);

        let _ = server.poll_next_unpin(&mut noop_cx);

        let Poll::Ready(Some(FakeServerEvent::WriteResponded { handle, value, .. })) =
            event_stream.poll_unpin(&mut noop_cx)
        else {
            panic!("Expected WriteResponded event");
        };
        assert_eq!(handle, Handle(2));
        assert_matches!(
            value.unwrap_err(),
            bt_gatt::types::Error::Gatt(GattError::WriteNotPermitted)
        );
    }

    #[test]
    fn control_point_empty_payload_fails() {
        let (mut server, fake_gatt_server, mut event_receiver, mut noop_cx) =
            setup_test_server(vec![BroadcastReceiveState::Empty]);
        let mut event_stream = event_receiver.next();

        // Writing empty payload to Control Point
        fake_gatt_server.incoming_write(PeerId(1), BASS_SERVICE_ID, Handle(1), 0, vec![]);

        let _ = server.poll_next_unpin(&mut noop_cx);

        let Poll::Ready(Some(FakeServerEvent::WriteResponded { handle, value, .. })) =
            event_stream.poll_unpin(&mut noop_cx)
        else {
            panic!("Expected WriteResponded event");
        };
        assert_eq!(handle, Handle(1));
        assert_matches!(
            value.unwrap_err(),
            bt_gatt::types::Error::Gatt(GattError::WriteRequestRejected)
        );
    }

    #[test]
    fn read_control_point_fails() {
        let (mut server, fake_gatt_server, mut event_receiver, mut noop_cx) =
            setup_test_server(vec![BroadcastReceiveState::Empty]);
        let mut event_stream = event_receiver.next();

        fake_gatt_server.incoming_read(PeerId(1), BASS_SERVICE_ID, CONTROL_POINT_HANDLE, 0);
        let _ = server.poll_next_unpin(&mut noop_cx);
        let Poll::Ready(Some(FakeServerEvent::ReadResponded { handle, value, .. })) =
            event_stream.poll_unpin(&mut noop_cx)
        else {
            panic!("Expected ReadResponded event");
        };
        assert_eq!(handle, CONTROL_POINT_HANDLE);
        assert_matches!(
            value.unwrap_err(),
            bt_gatt::types::Error::Gatt(GattError::ReadNotPermitted)
        );
    }

    #[test]
    fn read_receive_state_invalid_offset() {
        let (mut server, fake_gatt_server, mut event_receiver, mut noop_cx) =
            setup_test_server(vec![BroadcastReceiveState::Empty]);
        let mut event_stream = event_receiver.next();

        fake_gatt_server.incoming_read(PeerId(1), BASS_SERVICE_ID, Handle(2), 10);
        let _ = server.poll_next_unpin(&mut noop_cx);
        let Poll::Ready(Some(FakeServerEvent::ReadResponded { handle, value, .. })) =
            event_stream.poll_unpin(&mut noop_cx)
        else {
            panic!("Expected ReadResponded event");
        };
        assert_eq!(handle, Handle(2));
        assert_matches!(value.unwrap_err(), bt_gatt::types::Error::Gatt(GattError::InvalidOffset));
    }

    #[test]
    fn publish_failure() {
        let mut noop_cx = Context::from_waker(futures::task::noop_waker_ref());

        let mut server = ServerBuilder::new()
            .add_receive_state_characteristic(BroadcastReceiveState::Empty)
            .build::<FakeTypes>()
            .expect("building server works");

        let (fake_gatt_server, _event_receiver) = FakeServer::new();
        fake_gatt_server
            .set_next_prepare_result(Err(bt_gatt::types::Error::Gatt(GattError::UnlikelyError)));

        assert!(server.publish(fake_gatt_server).is_ok());

        assert_matches!(
            server.poll_next_unpin(&mut noop_cx),
            Poll::Ready(Some(Err(Error::Gatt(bt_gatt::types::Error::Gatt(
                GattError::UnlikelyError
            )))))
        );

        // Verifying server reset state to NotPublished so it is not published
        assert!(!server.is_published());
    }

    #[test]
    fn builder_normalizes_source_id() {
        // Create state with an arbitrary source_id = 99
        let state = make_test_receive_state(99);
        let (mut server, fake_gatt_server, mut event_receiver, mut noop_cx) =
            setup_test_server(vec![state]);
        let mut event_stream = event_receiver.next();

        // Verify slot's internal state and encoded read value have source_id =
        // 1
        fake_gatt_server.incoming_read(PeerId(1), BASS_SERVICE_ID, Handle(2), 0);
        let _ = server.poll_next_unpin(&mut noop_cx);
        let Poll::Ready(Some(FakeServerEvent::ReadResponded { handle: _, value, .. })) =
            event_stream.poll_unpin(&mut noop_cx)
        else {
            panic!("Expected ReadResponded event");
        };
        let buf = value.expect("ok");
        assert_eq!(buf[0], 1);
    }

    #[test]
    fn add_receive_state_success() {
        let (mut server, fake_gatt_server, mut event_receiver, mut noop_cx) =
            setup_test_server(vec![BroadcastReceiveState::Empty]);
        let mut event_stream = event_receiver.next();

        fake_gatt_server.incoming_client_configuration(
            PeerId(10),
            BASS_SERVICE_ID,
            Handle(2),
            bt_gatt::server::NotificationType::Notify,
        );
        let _ = server.poll_next_unpin(&mut noop_cx);

        let state = make_test_inner_receive_state(99);
        let result = server.add_receive_state(state);
        assert_eq!(result.expect("add ok"), 1);

        // Expect the GATT notification for the updated characteristic.
        let Poll::Ready(Some(FakeServerEvent::Notified { handle, value, peers, .. })) =
            event_stream.poll_unpin(&mut noop_cx)
        else {
            panic!("Expected Notified event");
        };
        assert_eq!(handle, Handle(2));
        assert_eq!(value[0], 1);
        assert_eq!(peers, vec![PeerId(10)]);
    }

    #[test]
    fn add_receive_state_when_full_fails() {
        let (mut server, _fake_gatt_server, _event_receiver, _noop_cx) =
            setup_test_server(vec![make_test_receive_state(1)]);

        let state = make_test_inner_receive_state(2);
        let result = server.add_receive_state(state);
        assert_matches!(result, Err(Error::ServerFull));
    }

    #[test]
    fn update_receive_state_invalid_source_id_fails() {
        let (mut server, _fake_gatt_server, _event_receiver, _noop_cx) =
            setup_test_server(vec![BroadcastReceiveState::Empty]);

        let state = make_test_inner_receive_state(99);
        let result = server.update_receive_state(state);
        assert_matches!(result, Err(Error::InvalidSourceId(99)));
    }

    #[test]
    fn update_receive_state_notifies_peers() {
        let (mut server, fake_gatt_server, mut event_receiver, mut noop_cx) =
            setup_test_server(vec![make_test_receive_state(1)]);
        let mut event_stream = event_receiver.next();

        fake_gatt_server.incoming_client_configuration(
            PeerId(10),
            BASS_SERVICE_ID,
            Handle(2),
            bt_gatt::server::NotificationType::Notify,
        );
        let _ = server.poll_next_unpin(&mut noop_cx);

        let new_inner = make_test_inner_receive_state(1);
        let expected_state = BroadcastReceiveState::NonEmpty(new_inner.clone());
        let mut expected_bytes = vec![0u8; expected_state.encoded_len()];
        expected_state.encode(&mut expected_bytes).expect("encode ok");

        let result = server.update_receive_state(new_inner);
        assert!(result.is_ok());

        let Poll::Ready(Some(FakeServerEvent::Notified { handle, value, peers, .. })) =
            event_stream.poll_unpin(&mut noop_cx)
        else {
            panic!("Expected Notified event");
        };
        assert_eq!(handle, Handle(2));
        assert_eq!(value, expected_bytes);
        assert_eq!(peers, vec![PeerId(10)]);
    }

    #[test]
    fn clear_receive_state_success() {
        let (mut server, fake_gatt_server, mut event_receiver, mut noop_cx) =
            setup_test_server(vec![make_test_receive_state(1)]);
        let mut event_stream = event_receiver.next();

        fake_gatt_server.incoming_client_configuration(
            PeerId(10),
            BASS_SERVICE_ID,
            Handle(2),
            bt_gatt::server::NotificationType::Notify,
        );
        let _ = server.poll_next_unpin(&mut noop_cx);

        let result = server.clear_receive_state(1);
        assert!(result.is_ok());

        let Poll::Ready(Some(FakeServerEvent::Notified { handle, value, peers, .. })) =
            event_stream.poll_unpin(&mut noop_cx)
        else {
            panic!("Expected Notified event");
        };
        assert_eq!(handle, Handle(2));
        assert!(value.is_empty());
        assert_eq!(peers, vec![PeerId(10)]);
    }

    #[test]
    fn clear_and_reuse_receive_state_slot() {
        let (mut server, _fake_gatt_server, _event_receiver, _noop_cx) =
            setup_test_server(vec![make_test_receive_state(1)]);

        // Clear existing state in slot 1
        assert!(server.clear_receive_state(1).is_ok());

        // Adding a new state should successfully reuse the cleared slot and
        // allocate the next ID
        let new_state = make_test_inner_receive_state(50);
        let result = server.add_receive_state(new_state);
        assert_eq!(result.expect("add ok"), 2);
    }

    #[test]
    fn add_receive_state_sequential_slots() {
        let (mut server, _fake_gatt_server, _event_receiver, _noop_cx) = setup_test_server(vec![
            BroadcastReceiveState::Empty,
            BroadcastReceiveState::Empty,
            BroadcastReceiveState::Empty,
        ]);

        let state1 = make_test_inner_receive_state(10);
        let state2 = make_test_inner_receive_state(20);
        let state3 = make_test_inner_receive_state(30);

        assert_eq!(server.add_receive_state(state1).unwrap(), 1);
        assert_eq!(server.add_receive_state(state2).unwrap(), 2);
        assert_eq!(server.add_receive_state(state3).unwrap(), 3);

        // Fourth add should fail as server is full
        let state4 = make_test_inner_receive_state(40);
        assert_matches!(server.add_receive_state(state4), Err(Error::ServerFull));
    }

    #[test]
    fn read_cleared_receive_state_returns_empty() {
        let (mut server, fake_gatt_server, mut event_receiver, mut noop_cx) =
            setup_test_server(vec![make_test_receive_state(1)]);
        let mut event_stream = event_receiver.next();

        // Clear the state
        assert!(server.clear_receive_state(1).is_ok());

        // Perform a GATT Read on Handle(2)
        fake_gatt_server.incoming_read(PeerId(10), BASS_SERVICE_ID, Handle(2), 0);
        let _ = server.poll_next_unpin(&mut noop_cx);

        let Poll::Ready(Some(FakeServerEvent::ReadResponded { handle, value, .. })) =
            event_stream.poll_unpin(&mut noop_cx)
        else {
            panic!("Expected ReadResponded event");
        };
        assert_eq!(handle, Handle(2));
        let buf = value.expect("read ok");
        assert!(buf.is_empty());
    }

    #[test]
    fn update_receive_state_encoding_failure_preserves_state() {
        let initial_inner = make_test_inner_receive_state(1);

        let (mut server, fake_gatt_server, mut event_receiver, mut noop_cx) =
            setup_test_server(vec![BroadcastReceiveState::NonEmpty(initial_inner.clone())]);
        let mut event_stream = event_receiver.next();

        // Create an invalid ReceiveState whose metadata total length exceeds
        // 255 bytes (causing BigSubgroup encode to fail)
        let vendor_metadata = vec![Metadata::AudioActiveState(true); 130];
        let mut invalid_inner = initial_inner.clone();
        invalid_inner.subgroups = vec![BigSubgroup::new(None).with_metadata(vendor_metadata)];

        // Attempting to update to invalid_inner should return a Packet encoding
        // error
        let result = server.update_receive_state(invalid_inner);
        assert_matches!(result, Err(Error::Packet(_)));

        // Perform a GATT Read on Handle(2) to verify internal memory state was
        // NOT mutated to invalid_state
        fake_gatt_server.incoming_read(PeerId(10), BASS_SERVICE_ID, Handle(2), 0);
        let _ = server.poll_next_unpin(&mut noop_cx);

        let Poll::Ready(Some(FakeServerEvent::ReadResponded { handle, value, .. })) =
            event_stream.poll_unpin(&mut noop_cx)
        else {
            panic!("Expected ReadResponded event");
        };
        assert_eq!(handle, Handle(2));

        // Read value should successfully decode back to initial_inner state
        let buf = value.expect("read ok");
        let (decoded_state, _) = BroadcastReceiveState::decode(&buf);
        assert_eq!(
            decoded_state.expect("decode ok"),
            BroadcastReceiveState::NonEmpty(initial_inner)
        );
    }

    #[test]
    fn allocate_source_id_skips_in_use_ids() {
        let mut state = ServerState::new(5);
        state.source_id_to_handle.insert(1, Handle(10));
        // Force the next ID to be 1 to simulate wrap around.
        state.next_source_id = NonZeroU8::new(1).unwrap();

        let allocated_id = state.allocate_source_id(Handle(20)).unwrap();
        assert_eq!(allocated_id, 2);
        assert_eq!(state.source_id_to_handle.get(&2), Some(&Handle(20)));
    }

    #[test]
    fn allocate_source_id_error_when_full() {
        let mut state = ServerState::new(255);
        for id in 1..=255 {
            state.source_id_to_handle.insert(id, Handle(u64::from(id)));
        }

        assert_eq!(state.allocate_source_id(Handle(300)), Err(GattError::InsufficientResources));
    }
}
