// 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 Media Control Service (MCS) server.

use bt_common::packet_encoding::Decodable;
use bt_common::{PeerId, Uuid};
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::channel::oneshot;
use futures::stream::{FuturesUnordered, Stream};
use futures::FutureExt;
use pin_project::pin_project;
use std::future::Future;
use std::pin::Pin;
use std::task::{Context, Poll, Waker};

use crate::types::*;
use crate::Error;

// ============================================================================
// Mandatory Characteristic Handle Definitions (MCS v1.0.1 Section 3)
// ============================================================================

/// Handle assigned to the Media Player Name characteristic.
const MEDIA_PLAYER_NAME_HANDLE: Handle = Handle(1);
/// Handle assigned to the Track Changed characteristic.
const TRACK_CHANGED_HANDLE: Handle = Handle(2);
/// Handle assigned to the Track Title characteristic.
const TRACK_TITLE_HANDLE: Handle = Handle(3);
/// Handle assigned to the Track Duration characteristic.
const TRACK_DURATION_HANDLE: Handle = Handle(4);
/// Handle assigned to the Track Position characteristic.
const TRACK_POSITION_HANDLE: Handle = Handle(5);
/// Handle assigned to the Media State characteristic.
const MEDIA_STATE_HANDLE: Handle = Handle(6);
/// Handle assigned to the Content Control ID (CCID) characteristic.
const CONTENT_CONTROL_ID_HANDLE: Handle = Handle(7);

// ============================================================================
// Optional Characteristic Handle Definitions (MCS v1.0.1 Section 3)
// ============================================================================

/// Handle assigned to the Media Player Icon URL characteristic.
const MEDIA_PLAYER_ICON_URL_HANDLE: Handle = Handle(8);
/// Handle assigned to the Playback Speed characteristic.
const PLAYBACK_SPEED_HANDLE: Handle = Handle(9);
/// Handle assigned to the Seeking Speed characteristic.
const SEEKING_SPEED_HANDLE: Handle = Handle(10);
/// Handle assigned to the Playing Order characteristic.
const PLAYING_ORDER_HANDLE: Handle = Handle(11);
/// Handle assigned to the Playing Orders Supported characteristic.
const PLAYING_ORDERS_SUPPORTED_HANDLE: Handle = Handle(12);
/// Handle assigned to the Media Control Point characteristic.
const MEDIA_CONTROL_POINT_HANDLE: Handle = Handle(13);
/// Handle assigned to the Media Control Point Opcodes Supported characteristic.
const MEDIA_CONTROL_POINT_OPCODES_SUPPORTED_HANDLE: Handle = Handle(14);

/// The mandatory characteristics defined in MCS v1.0.1 Section 3, Table 3.1.
fn mandatory_characteristics() -> [Characteristic; 7] {
    [
        build_characteristic(
            MEDIA_PLAYER_NAME_HANDLE,
            MEDIA_PLAYER_NAME_UUID,
            CharacteristicProperties::READ_NOTIFY,
        ),
        build_characteristic(
            TRACK_CHANGED_HANDLE,
            TRACK_CHANGED_UUID,
            CharacteristicProperty::Notify,
        ),
        build_characteristic(
            TRACK_TITLE_HANDLE,
            TRACK_TITLE_UUID,
            CharacteristicProperties::READ_NOTIFY,
        ),
        build_characteristic(
            TRACK_DURATION_HANDLE,
            TRACK_DURATION_UUID,
            CharacteristicProperties::READ_NOTIFY,
        ),
        build_characteristic(
            TRACK_POSITION_HANDLE,
            TRACK_POSITION_UUID,
            CharacteristicProperties::READ_WRITE_NOTIFY,
        ),
        build_characteristic(
            MEDIA_STATE_HANDLE,
            MEDIA_STATE_UUID,
            CharacteristicProperties::READ_NOTIFY,
        ),
        build_characteristic(
            CONTENT_CONTROL_ID_HANDLE,
            CONTENT_CONTROL_ID_UUID,
            CharacteristicProperty::Read,
        ),
    ]
}

/// Constructs a characteristic definition with the specified handle, UUID,
/// properties, and encryption-required permissions conforming to MCS v1.0.1
/// Section 3.
fn build_characteristic(
    handle: Handle,
    uuid: Uuid,
    properties: impl Into<CharacteristicProperties>,
) -> Characteristic {
    let properties = properties.into();
    Characteristic {
        handle,
        uuid,
        properties,
        permissions: AttributePermissions::with_levels(
            &properties,
            &SecurityLevels::encryption_required(),
        ),
        descriptors: Vec::new(),
    }
}

/// Internal state for the MCS server.
#[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 notify(&self, handle: &Handle, data: &[u8], peers: &[PeerId]) {
        if let LocalServiceState::Published { service, .. } = self {
            service.notify(handle, data, peers);
        }
    }
}

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

    fn poll_next(
        mut self: std::pin::Pin<&mut Self>,
        cx: &mut 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 } => match futures::ready!(fut.poll(cx)) {
                    Ok(service) => {
                        let events = service.publish();
                        self.as_mut().set(LocalServiceState::Published { service, events });
                    }
                    Err(e) => {
                        self.as_mut().set(LocalServiceState::NotPublished { waker: None });
                        return Poll::Ready(Some(Err(Error::Gatt(e))));
                    }
                },
                LocalServiceProj::Published { service: _, events } => {
                    match futures::ready!(events.poll_next(cx)) {
                        Some(Ok(event)) => return Poll::Ready(Some(Ok(event))),
                        Some(Err(e)) => {
                            self.as_mut().set(LocalServiceState::Terminated);
                            return Poll::Ready(Some(Err(Error::Gatt(e))));
                        }
                        // Deferred to McsServer to allow draining in-flight control point
                        // responses.
                        None => return Poll::Ready(None),
                    }
                }
            }
        }
    }
}

/// Confirms the updated track position to store in local state and notify to
/// clients.
/// It is safe to drop without responding to ignore the update or if the value
/// has not changed.
pub type SetTrackPositionResponder = SetValueResponder<TrackPosition>;

/// Confirms the updated playback speed to store in local state and notify to
/// clients.
/// It is safe to drop without responding to ignore the update or if the value
/// has not changed.
pub type SetPlaybackSpeedResponder = SetValueResponder<PlaybackSpeed>;

/// Confirms the updated playing order to store in local state and notify to
/// clients.
/// It is safe to drop without responding to ignore the update or if the value
/// has not changed.
pub type SetPlayingOrderResponder = SetValueResponder<PlayingOrder>;

/// Confirms the media control command result code to notify to the client.
/// A response is expected to confirm the result. If no response is provided,
/// then it is assumed that the Control Point request has failed and
/// `ControlPointResultCode::CommandCannotBeCompleted` will be sent to the peer.
pub type ControlPointWriteResponder = SetValueResponder<ControlPointResultCode>;

/// Responder for an asynchronous characteristic write or control point command.
///
/// Calling [`send`](Self::send) confirms the new value or command result to
/// update local state and notify clients. It is safe to drop the responder
/// without responding to cancel the update (or report command failure).
pub struct SetValueResponder<T> {
    response_tx: oneshot::Sender<T>,
}

impl<T: std::fmt::Debug> SetValueResponder<T> {
    /// Confirms the value or result code determined by the media player
    /// application and dispatches the corresponding GATT notification.
    pub fn send(self, value: T) {
        if let Err(result) = self.response_tx.send(value) {
            log::warn!("Failed to send response: server dropped or closed: {result:?}");
        }
    }
}

impl<T> std::fmt::Debug for SetValueResponder<T> {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        f.debug_struct("SetValueResponder").finish_non_exhaustive()
    }
}

/// An in-flight handler for a single-value asynchronous write response.
struct SetValueResponseFut<T> {
    rx: oneshot::Receiver<T>,
}

impl<T> SetValueResponseFut<T> {
    fn create() -> (Self, SetValueResponder<T>) {
        let (tx, rx) = oneshot::channel();
        (Self { rx }, SetValueResponder { response_tx: tx })
    }
}

impl<T> Future for SetValueResponseFut<T> {
    type Output = Option<T>;

    fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
        self.rx.poll_unpin(cx).map(Result::ok)
    }
}

/// Responses produced when an in-flight asynchronous write response completes.
enum PendingWriteResponse {
    ControlPoint {
        peer_id: PeerId,
        opcode: MediaControlOpcode,
        result_code: ControlPointResultCode,
    },
    TrackPosition(TrackPosition),
    PlaybackSpeed(PlaybackSpeed),
    PlayingOrder(PlayingOrder),
}

/// An in-flight asynchronous write response future.
enum PendingWriteResponseFut {
    ControlPoint {
        peer_id: PeerId,
        opcode: MediaControlOpcode,
        fut: SetValueResponseFut<ControlPointResultCode>,
    },
    TrackPosition(SetValueResponseFut<TrackPosition>),
    PlaybackSpeed(SetValueResponseFut<PlaybackSpeed>),
    PlayingOrder(SetValueResponseFut<PlayingOrder>),
}

impl Future for PendingWriteResponseFut {
    type Output = Option<PendingWriteResponse>;

    fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
        match self.as_mut().get_mut() {
            Self::ControlPoint { peer_id, opcode, fut } => fut.poll_unpin(cx).map(|res| {
                let code = res.unwrap_or(ControlPointResultCode::CommandCannotBeCompleted);
                Some(PendingWriteResponse::ControlPoint {
                    peer_id: *peer_id,
                    opcode: opcode.clone(),
                    result_code: code,
                })
            }),
            Self::TrackPosition(fut) => {
                fut.poll_unpin(cx).map(|res| res.map(PendingWriteResponse::TrackPosition))
            }
            Self::PlaybackSpeed(fut) => {
                fut.poll_unpin(cx).map(|res| res.map(PendingWriteResponse::PlaybackSpeed))
            }
            Self::PlayingOrder(fut) => {
                fut.poll_unpin(cx).map(|res| res.map(PendingWriteResponse::PlayingOrder))
            }
        }
    }
}

/// Events produced by an [`McsServer`] stream representing client actions that
/// require additional upper-layer application processing.
#[derive(Debug)]
pub enum McsServerEvent {
    /// Request to set the track playback position.
    SetTrackPosition {
        peer_id: PeerId,
        position: TrackPosition,
        responder: SetValueResponder<TrackPosition>,
    },
    /// Request to set the playback speed.
    SetPlaybackSpeed {
        peer_id: PeerId,
        speed: PlaybackSpeed,
        responder: SetValueResponder<PlaybackSpeed>,
    },
    /// Request to set the playing order.
    SetPlayingOrder {
        peer_id: PeerId,
        order: PlayingOrder,
        responder: SetValueResponder<PlayingOrder>,
    },
    /// Request to execute a media control command.
    ControlPointCommand {
        opcode: MediaControlOpcode,
        responder: SetValueResponder<ControlPointResultCode>,
    },
}

/// State of the playing order characteristics when enabled on the server.
#[derive(Debug, Clone, PartialEq, Eq)]
struct PlayingOrderState {
    /// Currently selected playing order.
    current: PlayingOrder,
    /// Bitmask of supported playing orders.
    supported: SupportedPlayingOrders,
}

impl PlayingOrderState {
    /// Creates a new `PlayingOrderState` with the default current order
    /// (`PlayingOrder::InOrderOnce`) and the given supported bitmask.
    fn new(supported: SupportedPlayingOrders) -> Self {
        Self { current: PlayingOrder::default(), supported }
    }

    /// Sets the playing order if it is supported.
    ///
    /// Returns `true` if `order` was supported and applied, or `false` if
    /// ignored because it was unsupported (MCS v1.0.1 Section 3.15.1).
    fn set_order(&mut self, order: PlayingOrder) -> bool {
        if self.supported.contains(order.into()) {
            self.current = order;
            true
        } else {
            false
        }
    }
}

/// Local state of the characteristics in this server.
#[derive(Debug, Clone, PartialEq, Eq)]
struct McsLocalState {
    /// Content Control ID (CCID) identifying this media service instance.
    ccid: u8,
    /// Human-readable media player application name.
    player_name: String,
    /// Title of the currently selected track (empty if no track loaded).
    track_title: String,
    /// Total duration of the current track (MCS v1.0.1 Section 3.6).
    track_duration: TrackDuration,
    /// Base playback position of the current track (MCS v1.0.1 Section 3.7).
    track_position: TrackPosition,
    /// Timestamp when `track_position` was set or updated.
    position_updated_at: Option<std::time::Instant>,
    /// Current player activity state.
    media_state: MediaState,
    /// URL pointing to media player icon graphic, if supported.
    icon_url: Option<String>,
    /// Playback speed multiplier, if supported.
    playback_speed: Option<PlaybackSpeed>,
    /// Seeking speed factor, if supported.
    seeking_speed: Option<SeekingSpeed>,
    /// Playing order and supported playing orders, if supported.
    playing_orders: Option<PlayingOrderState>,
    /// Supported media control point opcodes, if Media Control Point is
    /// supported.
    supported_opcodes: Option<SupportedOpcodes>,
}

impl McsLocalState {
    /// Creates a new [`McsLocalState`] with default values for an inactive
    /// player with no track loaded per MCS v1.0.1 Section 3.
    fn new(ccid: u8, player_name: impl Into<String>) -> Self {
        Self {
            ccid,
            player_name: player_name.into(),
            track_title: String::new(),
            track_duration: TrackDuration::Unknown,
            track_position: TrackPosition::Unavailable,
            position_updated_at: None,
            media_state: MediaState::Inactive,
            icon_url: None,
            playback_speed: None,
            seeking_speed: None,
            playing_orders: None,
            supported_opcodes: None,
        }
    }

    /// Calculates the instantaneous track position based on elapsed playback
    /// time (MCS v1.0.1 Section 3.7).
    fn current_track_position(&self) -> TrackPosition {
        // Per MCS Section 3.17, an inactive player has no current track, so it is
        // unavailable.
        if self.media_state == MediaState::Inactive {
            return TrackPosition::Unavailable;
        }

        // Playback timing has not started since the track was just initialized.
        let Some(updated_at) = self.position_updated_at else {
            return self.track_position;
        };

        // Playback is paused/seeking, so the position remains fixed.
        if self.media_state != MediaState::Playing {
            return self.track_position;
        }

        let base = match (self.track_position, self.track_duration) {
            (TrackPosition::FromStart(base), _) => base,
            (TrackPosition::FromEnd(end), TrackDuration::Duration(total)) => {
                total.saturating_sub(end)
            }
            _ => return self.track_position,
        };

        // TODO(b/540400364): Factor in optional playback speed when supported
        let mut current = base + updated_at.elapsed();
        if let TrackDuration::Duration(total) = self.track_duration {
            current = current.min(total);
        }
        TrackPosition::FromStart(current)
    }

    /// Sets the track position and records the update timestamp.
    fn set_track_position(&mut self, position: TrackPosition) {
        self.track_position = position;
        self.position_updated_at = Some(std::time::Instant::now());
    }

    /// Sets the playback speed.
    fn set_playback_speed(&mut self, speed: PlaybackSpeed) {
        self.playback_speed = Some(speed);
    }

    /// Sets the playing order if playing order is supported.
    fn set_playing_order(&mut self, order: PlayingOrder) {
        if let Some(ref mut orders) = self.playing_orders {
            let _ = orders.set_order(order);
        }
    }

    #[cfg(test)]
    pub(crate) fn set_media_state(&mut self, state: MediaState) {
        self.media_state = state;
    }

    #[cfg(test)]
    pub(crate) fn set_supported_opcodes(&mut self, opcodes: SupportedOpcodes) {
        self.supported_opcodes = Some(opcodes);
    }

    /// Reads the characteristic bytes for `handle` at `offset`.
    fn handle_read(&self, handle: Handle, offset: usize) -> Result<Vec<u8>, GattError> {
        let read_at_offset =
            |bytes: &[u8]| bytes.get(offset..).map(Vec::from).ok_or(GattError::InvalidOffset);

        match handle {
            // Track Changed and Media Control Point are not readable per MCS v1.0.1 Section 3,
            // Table 3.1.
            TRACK_CHANGED_HANDLE | MEDIA_CONTROL_POINT_HANDLE => Err(GattError::ReadNotPermitted),
            MEDIA_PLAYER_NAME_HANDLE => read_at_offset(self.player_name.as_bytes()),
            TRACK_TITLE_HANDLE => read_at_offset(self.track_title.as_bytes()),
            TRACK_DURATION_HANDLE => read_at_offset(&self.track_duration.raw_10ms().to_le_bytes()),
            TRACK_POSITION_HANDLE => {
                read_at_offset(&self.current_track_position().raw_10ms().to_le_bytes())
            }
            MEDIA_STATE_HANDLE => read_at_offset(&[self.media_state.into()]),
            CONTENT_CONTROL_ID_HANDLE => read_at_offset(&[self.ccid]),
            MEDIA_PLAYER_ICON_URL_HANDLE => {
                let url = self.icon_url.as_ref().ok_or(GattError::InvalidHandle)?;
                read_at_offset(url.as_bytes())
            }
            PLAYBACK_SPEED_HANDLE => {
                let speed = self.playback_speed.ok_or(GattError::InvalidHandle)?;
                read_at_offset(&[speed.into()])
            }
            SEEKING_SPEED_HANDLE => {
                let speed = self.seeking_speed.ok_or(GattError::InvalidHandle)?;
                read_at_offset(&[speed.into()])
            }
            PLAYING_ORDER_HANDLE => {
                let orders = self.playing_orders.as_ref().ok_or(GattError::InvalidHandle)?;
                read_at_offset(&[orders.current.into()])
            }
            PLAYING_ORDERS_SUPPORTED_HANDLE => {
                let orders = self.playing_orders.as_ref().ok_or(GattError::InvalidHandle)?;
                read_at_offset(&orders.supported.bits().to_le_bytes())
            }
            MEDIA_CONTROL_POINT_OPCODES_SUPPORTED_HANDLE => {
                let opcodes = self.supported_opcodes.ok_or(GattError::InvalidHandle)?;
                read_at_offset(&opcodes.bits().to_le_bytes())
            }
            _ => Err(GattError::InvalidHandle),
        }
    }
}

/// Builder for configuring an MCS or GMCS GATT service.
// TODO(b/549911651): Add support for OTS (Object Transfer Service) integration.
#[derive(Debug, Clone, PartialEq)]
pub struct McsServerBuilder {
    /// Service UUID assigned to the service.
    service_uuid: Uuid,
    /// Local state of the characteristics in this server.
    state: McsLocalState,
}

impl McsServerBuilder {
    /// Creates a builder for the Generic Media Control Service.
    pub fn generic(ccid: u8, player_name: impl Into<String>) -> Self {
        Self::new(GENERIC_MEDIA_CONTROL_SERVICE_UUID, ccid, player_name)
    }

    /// Creates a builder for an application-specific Media Control Service.
    pub fn instance(ccid: u8, player_name: impl Into<String>) -> Self {
        Self::new(MEDIA_CONTROL_SERVICE_UUID, ccid, player_name)
    }

    fn new(service_uuid: Uuid, ccid: u8, player_name: impl Into<String>) -> Self {
        Self { service_uuid, state: McsLocalState::new(ccid, player_name) }
    }

    /// Enables media player icon URL support.
    pub fn with_icon_url(mut self, url: impl Into<String>) -> Self {
        self.state.icon_url = Some(url.into());
        self
    }

    /// Enables playback and seeking speed support with default speeds.
    pub fn with_player_speeds(mut self) -> Self {
        self.state.playback_speed = Some(PlaybackSpeed::NORMAL);
        self.state.seeking_speed = Some(SeekingSpeed::NOT_SEEKING);
        self
    }

    /// Enables playing order support with the given supported playing orders.
    pub fn with_playing_orders(mut self, supported: SupportedPlayingOrders) -> Self {
        self.state.playing_orders = Some(PlayingOrderState::new(supported));
        self
    }

    /// Enables media control operations with the given supported opcodes.
    pub fn with_supported_operations(mut self, supported: SupportedOpcodes) -> Self {
        self.state.supported_opcodes = Some(supported);
        self
    }

    /// Constructs the GATT [`ServiceDefinition`] containing the mandatory
    /// characteristics per MCS v1.0.1 Section 3 and any configured optional
    /// characteristics.
    pub fn build_service_definition(&self) -> Result<ServiceDefinition, Error> {
        // The local `ServiceId` is derived from the provided `CCID`. This is valid
        // because the CCID must be unique across all MCS/GMCS instances on the
        // host server. Adding a duplicate characteristic will result in an
        // Error.
        let mut service_def = ServiceDefinition::new(
            ServiceId::new(self.state.ccid.into()),
            self.service_uuid,
            ServiceKind::Primary,
        );

        for chrc in mandatory_characteristics() {
            service_def.add_characteristic(chrc)?;
        }

        if self.state.icon_url.is_some() {
            service_def.add_characteristic(build_characteristic(
                MEDIA_PLAYER_ICON_URL_HANDLE,
                MEDIA_PLAYER_ICON_URL_UUID,
                CharacteristicProperty::Read,
            ))?;
        }
        if self.state.playback_speed.is_some() {
            service_def.add_characteristic(build_characteristic(
                PLAYBACK_SPEED_HANDLE,
                PLAYBACK_SPEED_UUID,
                CharacteristicProperties::READ_WRITE_NOTIFY,
            ))?;
        }
        if self.state.seeking_speed.is_some() {
            service_def.add_characteristic(build_characteristic(
                SEEKING_SPEED_HANDLE,
                SEEKING_SPEED_UUID,
                CharacteristicProperties::READ_NOTIFY,
            ))?;
        }
        if self.state.playing_orders.is_some() {
            service_def.add_characteristic(build_characteristic(
                PLAYING_ORDER_HANDLE,
                PLAYING_ORDER_UUID,
                CharacteristicProperties::READ_WRITE_NOTIFY,
            ))?;
            service_def.add_characteristic(build_characteristic(
                PLAYING_ORDERS_SUPPORTED_HANDLE,
                PLAYING_ORDERS_SUPPORTED_UUID,
                CharacteristicProperty::Read,
            ))?;
        }
        if self.state.supported_opcodes.is_some() {
            service_def.add_characteristic(build_characteristic(
                MEDIA_CONTROL_POINT_HANDLE,
                MEDIA_CONTROL_POINT_UUID,
                CharacteristicProperties::WRITE_NOTIFY,
            ))?;
            service_def.add_characteristic(build_characteristic(
                MEDIA_CONTROL_POINT_OPCODES_SUPPORTED_HANDLE,
                MEDIA_CONTROL_POINT_OPCODES_SUPPORTED_UUID,
                CharacteristicProperties::READ_NOTIFY,
            ))?;
        }

        Ok(service_def)
    }

    /// Builds an [`McsServer`] configured with this builder.
    pub fn build<T: bt_gatt::ServerTypes>(self) -> Result<McsServer<T>, Error> {
        let service_def = self.build_service_definition()?;
        Ok(McsServer::new(service_def, self.state))
    }
}

/// An instance of a Media Control Service (MCS) or Generic Media Control
/// Service (GMCS) GATT server.
#[pin_project(project = McsServerProj)]
pub struct McsServer<T: bt_gatt::ServerTypes> {
    service_def: ServiceDefinition,
    #[pin]
    local_service: LocalServiceState<T>,
    /// Local state of the characteristics in this server.
    state: McsLocalState,
    #[pin]
    pending_write_responses: FuturesUnordered<PendingWriteResponseFut>,
}

impl<T: bt_gatt::ServerTypes> McsServer<T> {
    fn new(service_def: ServiceDefinition, state: McsLocalState) -> Self {
        Self {
            service_def,
            local_service: Default::default(),
            state,
            pending_write_responses: FuturesUnordered::new(),
        }
    }

    /// Returns true if this server is a GMCS server.
    pub fn is_generic_service(&self) -> bool {
        self.service_def.uuid() == GENERIC_MEDIA_CONTROL_SERVICE_UUID
    }

    /// 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> {
        let LocalServiceState::NotPublished { waker } = &mut self.local_service else {
            return Err(Error::AlreadyPublished);
        };

        let waker = waker.take();
        self.local_service =
            LocalServiceState::Preparing { fut: server.prepare(self.service_def.clone()) };

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

        Ok(())
    }

    #[cfg(test)]
    pub(crate) fn set_media_state(&mut self, state: MediaState) {
        self.state.set_media_state(state);
    }

    #[cfg(test)]
    pub(crate) fn set_supported_opcodes(&mut self, opcodes: SupportedOpcodes) {
        self.state.set_supported_opcodes(opcodes);
    }
}

impl<'a, T: bt_gatt::ServerTypes> McsServerProj<'a, T> {
    fn handle_read<R: ReadResponder>(&self, handle: Handle, offset: usize, responder: R) {
        match self.state.handle_read(handle, offset) {
            Ok(bytes) => responder.respond(&bytes),
            Err(err) => responder.error(err),
        }
    }

    fn handle_write<W: WriteResponder>(
        &mut self,
        peer_id: PeerId,
        handle: Handle,
        offset: u32,
        value: &[u8],
        responder: W,
    ) -> Option<McsServerEvent> {
        // Reject non-zero offsets as MCS writable characteristics do not support
        // long writes.
        if offset != 0 {
            responder.error(GattError::InvalidOffset);
            return None;
        }

        match handle {
            MEDIA_CONTROL_POINT_HANDLE => {
                self.handle_control_point_write(peer_id, value, responder)
            }
            TRACK_POSITION_HANDLE => {
                if value.len() != 4 {
                    responder.error(GattError::InvalidAttributeValueLength);
                    return None;
                }
                let raw = i32::from_le_bytes(value.try_into().unwrap());
                let position = TrackPosition::from_raw_10ms(raw);
                responder.acknowledge();
                let (fut, resp) = SetValueResponseFut::create();
                self.pending_write_responses.push(PendingWriteResponseFut::TrackPosition(fut));
                Some(McsServerEvent::SetTrackPosition { peer_id, position, responder: resp })
            }
            PLAYBACK_SPEED_HANDLE => {
                if self.state.playback_speed.is_none() {
                    responder.error(GattError::InvalidHandle);
                    return None;
                }
                if value.len() != 1 {
                    responder.error(GattError::InvalidAttributeValueLength);
                    return None;
                }
                let speed = PlaybackSpeed::from(value[0] as i8);
                responder.acknowledge();
                let (fut, resp) = SetValueResponseFut::create();
                self.pending_write_responses.push(PendingWriteResponseFut::PlaybackSpeed(fut));
                Some(McsServerEvent::SetPlaybackSpeed { peer_id, speed, responder: resp })
            }
            PLAYING_ORDER_HANDLE => {
                let Some(ref playing_orders) = self.state.playing_orders else {
                    responder.error(GattError::InvalidHandle);
                    return None;
                };
                if value.len() != 1 {
                    responder.error(GattError::InvalidAttributeValueLength);
                    return None;
                }
                let Ok(order) = PlayingOrder::try_from(value[0]) else {
                    // Invalid playing order values (MCS v1.0.1 Section 3.15.1).
                    responder.acknowledge();
                    return None;
                };
                if !playing_orders.supported.contains(order.into()) {
                    // Unsupported playing order is ignored per MCS v1.0.1 Section 3.15.1.
                    responder.acknowledge();
                    return None;
                }
                responder.acknowledge();
                let (fut, resp) = SetValueResponseFut::create();
                self.pending_write_responses.push(PendingWriteResponseFut::PlayingOrder(fut));
                Some(McsServerEvent::SetPlayingOrder { peer_id, order, responder: resp })
            }
            // Read-only characteristics cannot be written to.
            MEDIA_PLAYER_NAME_HANDLE
            | TRACK_CHANGED_HANDLE
            | TRACK_TITLE_HANDLE
            | TRACK_DURATION_HANDLE
            | MEDIA_PLAYER_ICON_URL_HANDLE
            | SEEKING_SPEED_HANDLE
            | PLAYING_ORDERS_SUPPORTED_HANDLE
            | MEDIA_STATE_HANDLE
            | MEDIA_CONTROL_POINT_OPCODES_SUPPORTED_HANDLE
            | CONTENT_CONTROL_ID_HANDLE => {
                responder.error(GattError::WriteNotPermitted);
                None
            }
            // TODO(b/549911651): Add support for optional characteristics (e.g. Search Control
            // Point and OTS object IDs).
            _ => {
                responder.error(GattError::InvalidHandle);
                None
            }
        }
    }

    fn handle_control_point_write<W: WriteResponder>(
        &mut self,
        peer_id: PeerId,
        value: &[u8],
        responder: W,
    ) -> Option<McsServerEvent> {
        // The Media Control Point characteristic is optional - reject all requests if
        // it is not enabled on this server.
        let Some(supported_opcodes) = self.state.supported_opcodes else {
            responder.error(GattError::InvalidHandle);
            return None;
        };

        let Some(&raw_opcode) = value.first() else {
            responder.error(GattError::InvalidAttributeValueLength);
            return None;
        };

        let notify_error = |responder: W, result_code: ControlPointResultCode| {
            responder.acknowledge();
            self.local_service.notify(
                &MEDIA_CONTROL_POINT_HANDLE,
                &[raw_opcode, result_code.into()],
                &[peer_id],
            );
            None
        };

        // Validate opcode decoding and server opcode support (see MCS v1.0.1 Section
        // 3.18.2).
        let opcode = match MediaControlOpcode::decode(value) {
            (Ok(opcode), _) if supported_opcodes.contains((&opcode).into()) => opcode,
            _ => return notify_error(responder, ControlPointResultCode::OpcodeNotSupported),
        };

        // Reject commands if the media player is inactive.
        // TODO(b/540400364): The spec also technically allows the handling of the
        // command if the media player supports it with no active track. Revisit
        // this if needed.
        if self.state.media_state == MediaState::Inactive {
            return notify_error(responder, ControlPointResultCode::MediaPlayerInactive);
        }

        // Acknowledge the GATT write and produce a new event for the request.
        responder.acknowledge();
        let (fut, responder) = SetValueResponseFut::create();
        self.pending_write_responses.push(PendingWriteResponseFut::ControlPoint {
            peer_id,
            opcode: opcode.clone(),
            fut,
        });
        Some(McsServerEvent::ControlPointCommand { opcode, responder })
    }

    /// Attempts to handle a pending write response from the upper layer
    /// application.
    fn handle_pending_write_response(&mut self, response: PendingWriteResponse) {
        match response {
            PendingWriteResponse::ControlPoint { peer_id, opcode, result_code } => {
                // Dispatches a Media Control Point GATT notification containing
                // [opcode, result_code] to the peer per MCS v1.0.1 Section 3.18.2.
                self.local_service.notify(
                    &MEDIA_CONTROL_POINT_HANDLE,
                    &[opcode.raw_opcode(), result_code.into()],
                    &[peer_id],
                );
            }
            PendingWriteResponse::TrackPosition(position) => {
                self.state.set_track_position(position);
                self.local_service.notify(
                    &TRACK_POSITION_HANDLE,
                    &position.raw_10ms().to_le_bytes(),
                    &[],
                );
            }
            PendingWriteResponse::PlaybackSpeed(speed) => {
                self.state.set_playback_speed(speed);
                self.local_service.notify(&PLAYBACK_SPEED_HANDLE, &[speed.into()], &[]);
            }
            PendingWriteResponse::PlayingOrder(order) => {
                self.state.set_playing_order(order);
                self.local_service.notify(&PLAYING_ORDER_HANDLE, &[order.into()], &[]);
            }
        }
    }
}

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

    fn poll_next(
        mut self: std::pin::Pin<&mut Self>,
        cx: &mut Context<'_>,
    ) -> Poll<Option<Self::Item>> {
        loop {
            let mut this = self.as_mut().project();
            // Drain any completed asynchronous write responses before processing new
            // GATT events.
            if let Poll::Ready(Some(response)) = this.pending_write_responses.as_mut().poll_next(cx)
            {
                if let Some(response) = response {
                    this.handle_pending_write_response(response);
                }
                continue;
            }

            let gatt_event = match futures::ready!(this.local_service.as_mut().poll_next(cx)) {
                None => {
                    // Continue polling until all in-flight responses have been drained before
                    // terminating the stream.
                    if this.pending_write_responses.is_empty() {
                        this.local_service.as_mut().set(LocalServiceState::Terminated);
                        return Poll::Ready(None);
                    } else {
                        return Poll::Pending;
                    }
                }
                Some(Err(e)) => return Poll::Ready(Some(Err(e))),
                Some(Ok(event)) => event,
            };

            match gatt_event {
                ServiceEvent::Read { peer_id: _, handle, offset, responder } => {
                    this.handle_read(handle, offset as usize, responder);
                }
                ServiceEvent::Write { peer_id, handle, offset, value, responder } => {
                    let value_bytes = value.to_owned();
                    if let Some(event) =
                        this.handle_write(peer_id, handle, offset, &value_bytes, responder)
                    {
                        return Poll::Ready(Some(Ok(event)));
                    }
                }
                _ => continue,
            }
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    use assert_matches::assert_matches;
    use bt_gatt::test_utils::{FakeServer, FakeServerEvent, FakeTypes};
    use futures::StreamExt;

    #[test]
    fn builder_generic_service_definition() {
        let builder = McsServerBuilder::generic(0x42, "Test Generic Player");
        let service_def =
            builder.build_service_definition().expect("service definition builds successfully");
        assert_eq!(service_def.uuid(), GENERIC_MEDIA_CONTROL_SERVICE_UUID);
        assert_eq!(service_def.id(), ServiceId::new(0x42));
        assert_eq!(service_def.kind(), ServiceKind::Primary);
        assert_eq!(service_def.characteristics().count(), 7);
    }

    #[test]
    fn builder_instance_service_definition() {
        let builder = McsServerBuilder::instance(0x07, "Test Instance Player");
        let service_def = builder
            .build_service_definition()
            .expect("instance service definition builds successfully");
        assert_eq!(service_def.uuid(), MEDIA_CONTROL_SERVICE_UUID);
        assert_eq!(service_def.id(), ServiceId::new(0x07));
        assert_eq!(service_def.kind(), ServiceKind::Primary);
        assert_eq!(service_def.characteristics().count(), 7);
    }

    #[test]
    fn builder_with_optional_characteristics_service_definition() {
        let builder = McsServerBuilder::generic(0x10, "Full Player")
            .with_icon_url("https://example.com/icon.png")
            .with_player_speeds()
            .with_playing_orders(SupportedPlayingOrders::default())
            .with_supported_operations(SupportedOpcodes::default());

        let service_def =
            builder.build_service_definition().expect("service definition builds successfully");
        assert_eq!(service_def.characteristics().count(), 14);

        let characteristics: Vec<&Characteristic> = service_def.characteristics().collect();
        let expected_characteristics = [
            mandatory_characteristics()[0].clone(),
            mandatory_characteristics()[1].clone(),
            mandatory_characteristics()[2].clone(),
            mandatory_characteristics()[3].clone(),
            mandatory_characteristics()[4].clone(),
            mandatory_characteristics()[5].clone(),
            mandatory_characteristics()[6].clone(),
            build_characteristic(
                MEDIA_PLAYER_ICON_URL_HANDLE,
                MEDIA_PLAYER_ICON_URL_UUID,
                CharacteristicProperty::Read,
            ),
            build_characteristic(
                PLAYBACK_SPEED_HANDLE,
                PLAYBACK_SPEED_UUID,
                CharacteristicProperties::READ_WRITE_NOTIFY,
            ),
            build_characteristic(
                SEEKING_SPEED_HANDLE,
                SEEKING_SPEED_UUID,
                CharacteristicProperties::READ_NOTIFY,
            ),
            build_characteristic(
                PLAYING_ORDER_HANDLE,
                PLAYING_ORDER_UUID,
                CharacteristicProperties::READ_WRITE_NOTIFY,
            ),
            build_characteristic(
                PLAYING_ORDERS_SUPPORTED_HANDLE,
                PLAYING_ORDERS_SUPPORTED_UUID,
                CharacteristicProperty::Read,
            ),
            build_characteristic(
                MEDIA_CONTROL_POINT_HANDLE,
                MEDIA_CONTROL_POINT_UUID,
                CharacteristicProperties::WRITE_NOTIFY,
            ),
            build_characteristic(
                MEDIA_CONTROL_POINT_OPCODES_SUPPORTED_HANDLE,
                MEDIA_CONTROL_POINT_OPCODES_SUPPORTED_UUID,
                CharacteristicProperties::READ_NOTIFY,
            ),
        ];

        assert_eq!(characteristics.len(), expected_characteristics.len());
        for (i, expected) in expected_characteristics.iter().enumerate() {
            let chrc = characteristics[i];
            assert_eq!(chrc.handle, expected.handle);
            assert_eq!(chrc.uuid, expected.uuid);
            assert_eq!(chrc.properties, expected.properties);
        }
    }

    #[test]
    fn mandatory_characteristic_handles_uuids_and_properties() {
        let builder = McsServerBuilder::generic(0x01, "Player");
        let service_def =
            builder.build_service_definition().expect("service definition builds successfully");
        let characteristics: Vec<&Characteristic> = service_def.characteristics().collect();

        let expected_mandatory = mandatory_characteristics();
        assert_eq!(characteristics.len(), expected_mandatory.len());

        for (i, expected) in expected_mandatory.iter().enumerate() {
            let chrc = characteristics[i];
            assert_eq!(chrc.handle, expected.handle);
            assert_eq!(chrc.uuid, expected.uuid);
            assert_eq!(chrc.properties, expected.properties);

            assert_eq!(
                chrc.permissions.read.map(|s| s.encryption),
                expected.permissions.read.map(|s| s.encryption)
            );
            assert_eq!(
                chrc.permissions.write.map(|s| s.encryption),
                expected.permissions.write.map(|s| s.encryption)
            );
            assert_eq!(
                chrc.permissions.update.map(|s| s.encryption),
                expected.permissions.update.map(|s| s.encryption)
            );
        }
    }

    #[test]
    fn service_id_tracks_ccid() {
        let builder1 = McsServerBuilder::instance(0x05, "Player 1");
        let builder2 = McsServerBuilder::generic(0x05, "Player 2");
        let builder3 = McsServerBuilder::instance(0x06, "Player 3");

        let def1 =
            builder1.build_service_definition().expect("service definition builds successfully");
        let def2 =
            builder2.build_service_definition().expect("service definition builds successfully");
        let def3 =
            builder3.build_service_definition().expect("service definition builds successfully");

        assert_eq!(def1.id(), def2.id());
        assert_eq!(def1.id(), ServiceId::new(5));
        assert_ne!(def1.id(), def3.id());
        assert_eq!(def3.id(), ServiceId::new(6));
    }

    #[test]
    fn build_server_success() {
        let generic_server: McsServer<FakeTypes> =
            McsServerBuilder::generic(0x42, "Test Generic Player")
                .build()
                .expect("generic server builds successfully");
        assert!(!generic_server.is_published());
        assert!(generic_server.is_generic_service());

        let instance_server: McsServer<FakeTypes> =
            McsServerBuilder::instance(0x42, "Test Instance Player")
                .build()
                .expect("instance server builds successfully");
        assert!(!instance_server.is_published());
        assert!(!instance_server.is_generic_service());
    }

    #[test]
    fn publish_server_success() {
        let mut noop_cx = Context::from_waker(futures::task::noop_waker_ref());
        let mut server: McsServer<FakeTypes> =
            McsServerBuilder::generic(0x42, "Test Generic Player")
                .build()
                .expect("server builds successfully");
        assert!(!server.is_published());

        let (fake_gatt_server, _event_receiver) = FakeServer::new();
        let Poll::Pending = server.next().poll_unpin(&mut noop_cx) else {
            panic!("Should be pending before publish");
        };

        server.publish(fake_gatt_server).expect("publish succeeds");

        // Advance state: Preparing -> Published
        let Poll::Pending = server.next().poll_unpin(&mut noop_cx) else {
            panic!("Should be pending after publish");
        };
        assert!(server.is_published());
    }

    #[test]
    fn publish_server_already_published_error() {
        let (fake_gatt_server, _event_receiver) = FakeServer::new();
        let mut server: McsServer<FakeTypes> = McsServerBuilder::generic(0x42, "Test Player")
            .build()
            .expect("server builds successfully");

        server.publish(fake_gatt_server.clone()).expect("initial publish succeeds");
        let err = server.publish(fake_gatt_server);
        assert_matches!(err, Err(Error::AlreadyPublished));
    }

    #[test]
    fn duplicate_ccid_publish_error() {
        let mut noop_cx = Context::from_waker(futures::task::noop_waker_ref());
        let (fake_gatt_server, _event_receiver) = FakeServer::new();

        let mut server1: McsServer<FakeTypes> = McsServerBuilder::instance(0x05, "Player 1")
            .build()
            .expect("server1 builds successfully");
        let mut server2: McsServer<FakeTypes> = McsServerBuilder::instance(0x05, "Player 2")
            .build()
            .expect("server2 builds successfully");

        // The first server publishes successfully.
        server1.publish(fake_gatt_server.clone()).expect("server1 publish call succeeds");
        let _ = server1.next().poll_unpin(&mut noop_cx);
        assert!(server1.is_published());

        // The GATT server rejects the second server attempting to publish with the
        // duplicate CCID / ServiceId.
        fake_gatt_server.set_next_prepare_result(Err(bt_gatt::types::Error::AlreadyPublished(
            ServiceId::new(0x05),
        )));
        server2.publish(fake_gatt_server).expect("server2 publish call succeeds");
        let poll_result = server2.next().poll_unpin(&mut noop_cx);
        assert_matches!(
            poll_result,
            Poll::Ready(Some(Err(Error::Gatt(bt_gatt::types::Error::AlreadyPublished(_)))))
        );
    }

    #[test]
    fn server_stream_terminates_when_event_stream_closes() {
        let mut noop_cx = Context::from_waker(futures::task::noop_waker_ref());
        let (fake_gatt_server, _event_receiver) = FakeServer::new();
        let mut server: McsServer<FakeTypes> = McsServerBuilder::generic(0x42, "Test Player")
            .build()
            .expect("server builds successfully");

        server.publish(fake_gatt_server).expect("publish succeeds");

        // Advance to Published
        let Poll::Pending = server.next().poll_unpin(&mut noop_cx) else {
            panic!("Should be pending after publish");
        };
        assert!(server.is_published());

        // Replace local_service events stream with a custom channel that can be
        // explicitly closed.
        let (sender, receiver) = futures::channel::mpsc::unbounded();
        let LocalServiceState::Published { service, .. } =
            std::mem::replace(&mut server.local_service, LocalServiceState::Terminated)
        else {
            panic!("Expected server to be in Published state");
        };
        server.local_service = LocalServiceState::Published { service, events: receiver };

        // Dropping the sender closes the event stream.
        drop(sender);

        // Polling the server returns None indicating the stream has terminated.
        let poll_result = server.next().poll_unpin(&mut noop_cx);
        assert_matches!(poll_result, Poll::Ready(None));

        // Subsequent polls on terminated state also return None.
        let poll_result = server.next().poll_unpin(&mut noop_cx);
        assert_matches!(poll_result, Poll::Ready(None));
    }

    fn setup_test_server(
        builder: McsServerBuilder,
    ) -> (
        McsServer<FakeTypes>,
        FakeServer,
        futures::channel::mpsc::UnboundedReceiver<FakeServerEvent>,
    ) {
        let mut noop_cx = Context::from_waker(futures::task::noop_waker_ref());
        let (fake_gatt_server, mut event_receiver) = FakeServer::new();
        let mut server: McsServer<FakeTypes> = builder.build().expect("server builds successfully");
        server.publish(fake_gatt_server.clone()).expect("publish succeeds");
        let _ = server.next().poll_unpin(&mut noop_cx);
        assert!(matches!(event_receiver.try_recv().unwrap(), FakeServerEvent::Published { .. }));
        (server, fake_gatt_server, event_receiver)
    }

    fn setup_test_server_with_control_point(
        peer: PeerId,
    ) -> (
        McsServer<FakeTypes>,
        FakeServer,
        futures::channel::mpsc::UnboundedReceiver<FakeServerEvent>,
        Context<'static>,
    ) {
        let mut noop_cx = Context::from_waker(futures::task::noop_waker_ref());
        let (mut server, fake_gatt_server, mut event_receiver) = setup_test_server(
            McsServerBuilder::generic(0x42, "Test Player")
                .with_supported_operations(SupportedOpcodes::all()),
        );
        fake_gatt_server.incoming_client_configuration(
            peer,
            server.service_def.id(),
            MEDIA_CONTROL_POINT_HANDLE,
            bt_gatt::server::NotificationType::Notify,
        );
        let _ = server.next().poll_unpin(&mut noop_cx);
        let _ = event_receiver.try_recv();
        (server, fake_gatt_server, event_receiver, noop_cx)
    }

    fn assert_read_characteristic(
        server: &mut McsServer<FakeTypes>,
        fake_gatt_server: &FakeServer,
        event_receiver: &mut futures::channel::mpsc::UnboundedReceiver<FakeServerEvent>,
        handle: Handle,
        expected: &[u8],
    ) {
        let mut noop_cx = Context::from_waker(futures::task::noop_waker_ref());
        let peer = PeerId(1);
        let service_id = server.service_def.id();
        fake_gatt_server.incoming_read(peer, service_id, handle, 0);
        let _ = server.next().poll_unpin(&mut noop_cx);
        let bt_gatt::test_utils::FakeServerEvent::ReadResponded { value, .. } =
            event_receiver.try_recv().unwrap()
        else {
            panic!("expected ReadResponded");
        };
        assert_eq!(value.unwrap(), expected);
    }

    #[test]
    fn read_mandatory_characteristics_default_values() {
        let (mut server, fake_gatt_server, mut event_receiver) =
            setup_test_server(McsServerBuilder::generic(0x42, "Test Player"));

        // Media Player Name
        assert_read_characteristic(
            &mut server,
            &fake_gatt_server,
            &mut event_receiver,
            MEDIA_PLAYER_NAME_HANDLE,
            b"Test Player",
        );

        // Track Title
        assert_read_characteristic(
            &mut server,
            &fake_gatt_server,
            &mut event_receiver,
            TRACK_TITLE_HANDLE,
            b"",
        );

        // Track Duration
        assert_read_characteristic(
            &mut server,
            &fake_gatt_server,
            &mut event_receiver,
            TRACK_DURATION_HANDLE,
            &(-1i32).to_le_bytes(),
        );

        // Track Position
        assert_read_characteristic(
            &mut server,
            &fake_gatt_server,
            &mut event_receiver,
            TRACK_POSITION_HANDLE,
            &(-1i32).to_le_bytes(),
        );

        // Media State
        assert_read_characteristic(
            &mut server,
            &fake_gatt_server,
            &mut event_receiver,
            MEDIA_STATE_HANDLE,
            &[MediaState::Inactive.into()],
        );

        // Content Control ID
        assert_read_characteristic(
            &mut server,
            &fake_gatt_server,
            &mut event_receiver,
            CONTENT_CONTROL_ID_HANDLE,
            &[0x42],
        );
    }

    #[test]
    fn read_optional_characteristics_configured_values() {
        let (mut server, fake_gatt_server, mut event_receiver) = setup_test_server(
            McsServerBuilder::generic(0x42, "Test Player")
                .with_icon_url("https://example.com/icon.png")
                .with_player_speeds()
                .with_playing_orders(
                    SupportedPlayingOrders::IN_ORDER_ONCE | SupportedPlayingOrders::SHUFFLE_ONCE,
                )
                .with_supported_operations(SupportedOpcodes::PLAY | SupportedOpcodes::PAUSE),
        );

        // Media Player Icon URL
        assert_read_characteristic(
            &mut server,
            &fake_gatt_server,
            &mut event_receiver,
            MEDIA_PLAYER_ICON_URL_HANDLE,
            b"https://example.com/icon.png",
        );

        // Playback Speed
        assert_read_characteristic(
            &mut server,
            &fake_gatt_server,
            &mut event_receiver,
            PLAYBACK_SPEED_HANDLE,
            &[0],
        );

        // Seeking Speed
        assert_read_characteristic(
            &mut server,
            &fake_gatt_server,
            &mut event_receiver,
            SEEKING_SPEED_HANDLE,
            &[0],
        );

        // Playing Order
        assert_read_characteristic(
            &mut server,
            &fake_gatt_server,
            &mut event_receiver,
            PLAYING_ORDER_HANDLE,
            &[PlayingOrder::InOrderOnce.into()],
        );

        // Playing Orders Supported
        let expected_orders =
            SupportedPlayingOrders::IN_ORDER_ONCE | SupportedPlayingOrders::SHUFFLE_ONCE;
        assert_read_characteristic(
            &mut server,
            &fake_gatt_server,
            &mut event_receiver,
            PLAYING_ORDERS_SUPPORTED_HANDLE,
            &expected_orders.bits().to_le_bytes(),
        );

        // Media Control Point Opcodes Supported
        let expected_opcodes = SupportedOpcodes::PLAY | SupportedOpcodes::PAUSE;
        assert_read_characteristic(
            &mut server,
            &fake_gatt_server,
            &mut event_receiver,
            MEDIA_CONTROL_POINT_OPCODES_SUPPORTED_HANDLE,
            &expected_opcodes.bits().to_le_bytes(),
        );
    }

    #[test]
    fn read_unconfigured_optional_characteristics_returns_invalid_handle() {
        let (mut server, fake_gatt_server, mut event_receiver) =
            setup_test_server(McsServerBuilder::generic(0x42, "Mandatory Only Player"));

        let mut noop_cx = Context::from_waker(futures::task::noop_waker_ref());
        let peer = PeerId(1);
        let service_id = server.service_def.id();

        let unconfigured_handles = [
            MEDIA_PLAYER_ICON_URL_HANDLE,
            PLAYBACK_SPEED_HANDLE,
            SEEKING_SPEED_HANDLE,
            PLAYING_ORDER_HANDLE,
            PLAYING_ORDERS_SUPPORTED_HANDLE,
            MEDIA_CONTROL_POINT_OPCODES_SUPPORTED_HANDLE,
        ];

        for handle in unconfigured_handles {
            fake_gatt_server.incoming_read(peer, service_id, handle, 0);
            let _ = server.next().poll_unpin(&mut noop_cx);
            let bt_gatt::test_utils::FakeServerEvent::ReadResponded { value, .. } =
                event_receiver.try_recv().unwrap()
            else {
                panic!("expected ReadResponded for handle {:?}", handle);
            };
            assert_matches!(
                value.unwrap_err(),
                bt_gatt::types::Error::Gatt(GattError::InvalidHandle),
                "handle {:?} should return InvalidHandle when unconfigured",
                handle
            );
        }
    }

    #[test]
    fn write_unconfigured_optional_characteristics_returns_invalid_handle() {
        let (mut server, fake_gatt_server, mut event_receiver) =
            setup_test_server(McsServerBuilder::generic(0x42, "Mandatory Only Player"));

        let mut noop_cx = Context::from_waker(futures::task::noop_waker_ref());
        let peer = PeerId(1);
        let service_id = server.service_def.id();

        let unconfigured_writes = [
            (PLAYBACK_SPEED_HANDLE, vec![0x00]),
            (PLAYING_ORDER_HANDLE, vec![PlayingOrder::SingleOnce.into()]),
            (MEDIA_CONTROL_POINT_HANDLE, vec![MediaControlOpcode::Play.raw_opcode()]),
        ];

        for (handle, value) in unconfigured_writes {
            fake_gatt_server.incoming_write(peer, service_id, handle, 0, value);
            let poll_result = server.next().poll_unpin(&mut noop_cx);
            // Must NOT emit any McsServerEvent.
            assert_matches!(poll_result, Poll::Pending);
            let bt_gatt::test_utils::FakeServerEvent::WriteResponded { value, .. } =
                event_receiver.try_recv().unwrap()
            else {
                panic!("expected WriteResponded for handle {:?}", handle);
            };
            assert_matches!(
                value.unwrap_err(),
                bt_gatt::types::Error::Gatt(GattError::InvalidHandle),
                "handle {:?} should return InvalidHandle on write when unconfigured",
                handle
            );
        }
    }

    #[test]
    fn read_string_characteristics_with_offset() {
        let (mut server, fake_gatt_server, mut event_receiver) = setup_test_server(
            McsServerBuilder::generic(0x42, "Long Player Name")
                .with_icon_url("https://example.com/icon.png"),
        );

        let mut noop_cx = Context::from_waker(futures::task::noop_waker_ref());
        let peer = PeerId(1);
        let service_id = server.service_def.id();

        // Valid offset slice for Player Name
        fake_gatt_server.incoming_read(peer, service_id, MEDIA_PLAYER_NAME_HANDLE, 5);
        let _ = server.next().poll_unpin(&mut noop_cx);
        let bt_gatt::test_utils::FakeServerEvent::ReadResponded { value, .. } =
            event_receiver.try_recv().unwrap()
        else {
            panic!("expected ReadResponded");
        };
        assert_eq!(value.unwrap(), b"Player Name");

        // Valid offset slice for Icon URL
        fake_gatt_server.incoming_read(peer, service_id, MEDIA_PLAYER_ICON_URL_HANDLE, 8);
        let _ = server.next().poll_unpin(&mut noop_cx);
        let bt_gatt::test_utils::FakeServerEvent::ReadResponded { value, .. } =
            event_receiver.try_recv().unwrap()
        else {
            panic!("expected ReadResponded");
        };
        assert_eq!(value.unwrap(), b"example.com/icon.png");

        // Exact end offset returns empty slice
        fake_gatt_server.incoming_read(
            peer,
            service_id,
            MEDIA_PLAYER_NAME_HANDLE,
            "Long Player Name".len() as u32,
        );
        let _ = server.next().poll_unpin(&mut noop_cx);
        let bt_gatt::test_utils::FakeServerEvent::ReadResponded { value, .. } =
            event_receiver.try_recv().unwrap()
        else {
            panic!("expected ReadResponded");
        };
        assert_eq!(value.unwrap(), b"");

        // Out-of-bounds offset returns InvalidOffset
        fake_gatt_server.incoming_read(peer, service_id, MEDIA_PLAYER_NAME_HANDLE, 100);
        let _ = server.next().poll_unpin(&mut noop_cx);
        let bt_gatt::test_utils::FakeServerEvent::ReadResponded { value, .. } =
            event_receiver.try_recv().unwrap()
        else {
            panic!("expected ReadResponded");
        };
        assert_matches!(value.unwrap_err(), bt_gatt::types::Error::Gatt(GattError::InvalidOffset));

        // Out-of-bounds offset on Icon URL returns InvalidOffset
        fake_gatt_server.incoming_read(peer, service_id, MEDIA_PLAYER_ICON_URL_HANDLE, 100);
        let _ = server.next().poll_unpin(&mut noop_cx);
        let bt_gatt::test_utils::FakeServerEvent::ReadResponded { value, .. } =
            event_receiver.try_recv().unwrap()
        else {
            panic!("expected ReadResponded");
        };
        assert_matches!(value.unwrap_err(), bt_gatt::types::Error::Gatt(GattError::InvalidOffset));
    }

    #[test]
    fn read_non_readable_characteristics_returns_error() {
        let mut noop_cx = Context::from_waker(futures::task::noop_waker_ref());
        let (mut server, fake_gatt_server, mut event_receiver) = setup_test_server(
            McsServerBuilder::generic(0x42, "Test Player")
                .with_supported_operations(SupportedOpcodes::default()),
        );

        let peer = PeerId(1);
        let service_id = server.service_def.id();

        // Track Changed is notify-only
        fake_gatt_server.incoming_read(peer, service_id, TRACK_CHANGED_HANDLE, 0);
        let _ = server.next().poll_unpin(&mut noop_cx);
        let bt_gatt::test_utils::FakeServerEvent::ReadResponded { value, .. } =
            event_receiver.try_recv().unwrap()
        else {
            panic!("expected ReadResponded");
        };
        assert_matches!(
            value.unwrap_err(),
            bt_gatt::types::Error::Gatt(GattError::ReadNotPermitted)
        );

        // Media Control Point is write/notify-only
        fake_gatt_server.incoming_read(peer, service_id, MEDIA_CONTROL_POINT_HANDLE, 0);
        let _ = server.next().poll_unpin(&mut noop_cx);
        let bt_gatt::test_utils::FakeServerEvent::ReadResponded { value, .. } =
            event_receiver.try_recv().unwrap()
        else {
            panic!("expected ReadResponded");
        };
        assert_matches!(
            value.unwrap_err(),
            bt_gatt::types::Error::Gatt(GattError::ReadNotPermitted)
        );

        // Unknown handle returns InvalidHandle
        fake_gatt_server.incoming_read(peer, service_id, Handle(999), 0);
        let _ = server.next().poll_unpin(&mut noop_cx);
        let bt_gatt::test_utils::FakeServerEvent::ReadResponded { value, .. } =
            event_receiver.try_recv().unwrap()
        else {
            panic!("expected ReadResponded");
        };
        assert_matches!(value.unwrap_err(), bt_gatt::types::Error::Gatt(GattError::InvalidHandle));
    }

    #[test]
    fn write_track_position_success() {
        let (mut server, fake_gatt_server, mut event_receiver) =
            setup_test_server(McsServerBuilder::generic(0x42, "Test Player"));
        server.state.media_state = MediaState::Paused;
        let mut noop_cx = Context::from_waker(futures::task::noop_waker_ref());

        let peer = PeerId(1);
        let service_id = ServiceId::new(0x42);

        fake_gatt_server.incoming_client_configuration(
            peer,
            service_id,
            TRACK_POSITION_HANDLE,
            bt_gatt::server::NotificationType::Notify,
        );
        let _ = server.next().poll_unpin(&mut noop_cx);
        let _ = event_receiver.try_recv();

        fake_gatt_server.incoming_write(
            peer,
            service_id,
            TRACK_POSITION_HANDLE,
            0,
            4200i32.to_le_bytes().to_vec(),
        );

        let poll_result = server.next().poll_unpin(&mut noop_cx);
        let Poll::Ready(Some(Ok(McsServerEvent::SetTrackPosition {
            peer_id,
            position,
            responder,
        }))) = poll_result
        else {
            panic!("expected SetTrackPosition event, got {poll_result:?}");
        };
        assert_eq!(peer_id, peer);
        assert_eq!(position, TrackPosition::from_raw_10ms(4200));

        let FakeServerEvent::WriteResponded { value, .. } = event_receiver.try_recv().unwrap()
        else {
            panic!("expected WriteResponded");
        };
        assert!(value.is_ok());

        // Upper layer confirms the set track position.
        responder.send(position);

        // Server processes the confirmation, updates state, and sends notification.
        let _ = server.next().poll_unpin(&mut noop_cx);

        let FakeServerEvent::Notified { handle, value, peers, .. } =
            event_receiver.try_recv().unwrap()
        else {
            panic!("expected Notified");
        };
        assert_eq!(handle, TRACK_POSITION_HANDLE);
        assert_eq!(peers, vec![peer]);
        assert_eq!(value, 4200i32.to_le_bytes().to_vec());

        // Subsequent read reflects the updated track position
        fake_gatt_server.incoming_read(peer, service_id, TRACK_POSITION_HANDLE, 0);
        let _ = server.next().poll_unpin(&mut noop_cx);
        let FakeServerEvent::ReadResponded { value, .. } = event_receiver.try_recv().unwrap()
        else {
            panic!("expected ReadResponded");
        };
        assert_eq!(value.unwrap(), 4200i32.to_le_bytes());
    }

    #[test]
    fn write_track_position_invalid_length_or_offset() {
        let (mut server, fake_gatt_server, mut event_receiver) =
            setup_test_server(McsServerBuilder::generic(0x42, "Test Player"));
        let mut noop_cx = Context::from_waker(futures::task::noop_waker_ref());

        let peer = PeerId(1);
        let service_id = ServiceId::new(0x42);

        // Invalid offset (non-zero)
        fake_gatt_server.incoming_write(
            peer,
            service_id,
            TRACK_POSITION_HANDLE,
            1,
            4200i32.to_le_bytes().to_vec(),
        );
        let poll_result = server.next().poll_unpin(&mut noop_cx);
        assert_matches!(poll_result, Poll::Pending);
        let FakeServerEvent::WriteResponded { value, .. } = event_receiver.try_recv().unwrap()
        else {
            panic!("expected WriteResponded");
        };
        assert_matches!(value.unwrap_err(), bt_gatt::types::Error::Gatt(GattError::InvalidOffset));

        // Invalid value length (3 bytes instead of 4)
        fake_gatt_server.incoming_write(
            peer,
            service_id,
            TRACK_POSITION_HANDLE,
            0,
            vec![0x01, 0x02, 0x03],
        );
        let poll_result = server.next().poll_unpin(&mut noop_cx);
        assert_matches!(poll_result, Poll::Pending);
        let FakeServerEvent::WriteResponded { value, .. } = event_receiver.try_recv().unwrap()
        else {
            panic!("expected WriteResponded");
        };
        assert_matches!(
            value.unwrap_err(),
            bt_gatt::types::Error::Gatt(GattError::InvalidAttributeValueLength)
        );
    }

    #[test]
    fn write_playback_speed_success() {
        let (mut server, fake_gatt_server, mut event_receiver) =
            setup_test_server(McsServerBuilder::generic(0x42, "Test Player").with_player_speeds());
        let mut noop_cx = Context::from_waker(futures::task::noop_waker_ref());

        let peer = PeerId(1);
        let service_id = ServiceId::new(0x42);

        fake_gatt_server.incoming_client_configuration(
            peer,
            service_id,
            PLAYBACK_SPEED_HANDLE,
            bt_gatt::server::NotificationType::Notify,
        );
        let _ = server.next().poll_unpin(&mut noop_cx);
        let _ = event_receiver.try_recv();

        fake_gatt_server.incoming_write(
            peer,
            service_id,
            PLAYBACK_SPEED_HANDLE,
            0,
            vec![-64i8 as u8],
        );

        let poll_result = server.next().poll_unpin(&mut noop_cx);
        let Poll::Ready(Some(Ok(McsServerEvent::SetPlaybackSpeed { peer_id, speed, responder }))) =
            poll_result
        else {
            panic!("expected SetPlaybackSpeed event, got {poll_result:?}");
        };
        assert_eq!(peer_id, peer);
        assert_eq!(speed, PlaybackSpeed::HALF);

        let FakeServerEvent::WriteResponded { value, .. } = event_receiver.try_recv().unwrap()
        else {
            panic!("expected WriteResponded");
        };
        assert!(value.is_ok());

        // Upper layer confirms playback speed
        responder.send(speed);
        let _ = server.next().poll_unpin(&mut noop_cx);

        let FakeServerEvent::Notified { handle, value, peers, .. } =
            event_receiver.try_recv().unwrap()
        else {
            panic!("expected Notified");
        };
        assert_eq!(handle, PLAYBACK_SPEED_HANDLE);
        assert_eq!(peers, vec![peer]);
        assert_eq!(value, vec![-64i8 as u8]);

        // Subsequent read reflects the updated playback speed
        fake_gatt_server.incoming_read(peer, service_id, PLAYBACK_SPEED_HANDLE, 0);
        let _ = server.next().poll_unpin(&mut noop_cx);
        let FakeServerEvent::ReadResponded { value, .. } = event_receiver.try_recv().unwrap()
        else {
            panic!("expected ReadResponded");
        };
        assert_eq!(value.unwrap(), vec![-64i8 as u8]);
    }

    #[test]
    fn write_playback_speed_invalid_length_or_offset() {
        let (mut server, fake_gatt_server, mut event_receiver) =
            setup_test_server(McsServerBuilder::generic(0x42, "Test Player").with_player_speeds());
        let mut noop_cx = Context::from_waker(futures::task::noop_waker_ref());

        let peer = PeerId(1);
        let service_id = ServiceId::new(0x42);

        // Invalid offset (non-zero)
        fake_gatt_server.incoming_write(peer, service_id, PLAYBACK_SPEED_HANDLE, 1, vec![0x00]);
        let poll_result = server.next().poll_unpin(&mut noop_cx);
        assert_matches!(poll_result, Poll::Pending);
        let FakeServerEvent::WriteResponded { value, .. } = event_receiver.try_recv().unwrap()
        else {
            panic!("expected WriteResponded");
        };
        assert_matches!(value.unwrap_err(), bt_gatt::types::Error::Gatt(GattError::InvalidOffset));

        // Invalid value length (2 bytes instead of 1)
        fake_gatt_server.incoming_write(
            peer,
            service_id,
            PLAYBACK_SPEED_HANDLE,
            0,
            vec![0x00, 0x01],
        );
        let poll_result = server.next().poll_unpin(&mut noop_cx);
        assert_matches!(poll_result, Poll::Pending);
        let FakeServerEvent::WriteResponded { value, .. } = event_receiver.try_recv().unwrap()
        else {
            panic!("expected WriteResponded");
        };
        assert_matches!(
            value.unwrap_err(),
            bt_gatt::types::Error::Gatt(GattError::InvalidAttributeValueLength)
        );
    }

    #[test]
    fn write_playing_order_supported() {
        let (mut server, fake_gatt_server, mut event_receiver) = setup_test_server(
            McsServerBuilder::generic(0x42, "Test Player")
                .with_playing_orders(SupportedPlayingOrders::all()),
        );
        let mut noop_cx = Context::from_waker(futures::task::noop_waker_ref());

        let peer = PeerId(1);
        let service_id = ServiceId::new(0x42);

        fake_gatt_server.incoming_client_configuration(
            peer,
            service_id,
            PLAYING_ORDER_HANDLE,
            bt_gatt::server::NotificationType::Notify,
        );
        let _ = server.next().poll_unpin(&mut noop_cx);
        let _ = event_receiver.try_recv();

        fake_gatt_server.incoming_write(
            peer,
            service_id,
            PLAYING_ORDER_HANDLE,
            0,
            vec![PlayingOrder::ShuffleOnce.into()],
        );

        let poll_result = server.next().poll_unpin(&mut noop_cx);
        let Poll::Ready(Some(Ok(McsServerEvent::SetPlayingOrder { peer_id, order, responder }))) =
            poll_result
        else {
            panic!("expected SetPlayingOrder event, got {poll_result:?}");
        };
        assert_eq!(peer_id, peer);
        assert_eq!(order, PlayingOrder::ShuffleOnce);

        let FakeServerEvent::WriteResponded { value, .. } = event_receiver.try_recv().unwrap()
        else {
            panic!("expected WriteResponded");
        };
        assert!(value.is_ok());

        // Upper layer confirms playing order
        responder.send(order);
        let _ = server.next().poll_unpin(&mut noop_cx);

        let FakeServerEvent::Notified { handle, value, peers, .. } =
            event_receiver.try_recv().unwrap()
        else {
            panic!("expected Notified");
        };
        assert_eq!(handle, PLAYING_ORDER_HANDLE);
        assert_eq!(peers, vec![peer]);
        assert_eq!(value, vec![PlayingOrder::ShuffleOnce.into()]);

        // Subsequent read reflects the updated playing order
        fake_gatt_server.incoming_read(peer, service_id, PLAYING_ORDER_HANDLE, 0);
        let _ = server.next().poll_unpin(&mut noop_cx);
        let FakeServerEvent::ReadResponded { value, .. } = event_receiver.try_recv().unwrap()
        else {
            panic!("expected ReadResponded");
        };
        assert_eq!(value.unwrap(), vec![PlayingOrder::ShuffleOnce.into()]);
    }

    #[test]
    fn write_playing_order_unsupported_is_ignored() {
        let (mut server, fake_gatt_server, mut event_receiver) = setup_test_server(
            McsServerBuilder::generic(0x42, "Test Player")
                .with_playing_orders(SupportedPlayingOrders::IN_ORDER_ONCE),
        );
        let mut noop_cx = Context::from_waker(futures::task::noop_waker_ref());

        let peer = PeerId(1);
        let service_id = ServiceId::new(0x42);

        // Writing ShuffleOnce when only InOrderOnce is supported is ignored per MCS
        // v1.0.1 Section 3.15.1
        fake_gatt_server.incoming_write(
            peer,
            service_id,
            PLAYING_ORDER_HANDLE,
            0,
            vec![PlayingOrder::ShuffleOnce.into()],
        );

        let poll_result = server.next().poll_unpin(&mut noop_cx);
        assert_matches!(poll_result, Poll::Pending);

        let FakeServerEvent::WriteResponded { value, .. } = event_receiver.try_recv().unwrap()
        else {
            panic!("expected WriteResponded");
        };
        assert!(value.is_ok());

        // Value remains unchanged (InOrderOnce)
        fake_gatt_server.incoming_read(peer, service_id, PLAYING_ORDER_HANDLE, 0);
        let _ = server.next().poll_unpin(&mut noop_cx);
        let FakeServerEvent::ReadResponded { value, .. } = event_receiver.try_recv().unwrap()
        else {
            panic!("expected ReadResponded");
        };
        assert_eq!(value.unwrap(), vec![PlayingOrder::InOrderOnce.into()]);
    }

    #[test]
    fn write_read_only_characteristic_returns_error() {
        let (mut server, fake_gatt_server, mut event_receiver) =
            setup_test_server(McsServerBuilder::generic(0x42, "Test Player"));
        let mut noop_cx = Context::from_waker(futures::task::noop_waker_ref());

        let peer = PeerId(1);
        let service_id = ServiceId::new(0x42);

        let read_only_writes = [
            (MEDIA_PLAYER_NAME_HANDLE, b"New Name".to_vec()),
            (TRACK_CHANGED_HANDLE, vec![]),
            (TRACK_TITLE_HANDLE, b"New Title".to_vec()),
            (TRACK_DURATION_HANDLE, 1000i32.to_le_bytes().to_vec()),
            (MEDIA_PLAYER_ICON_URL_HANDLE, b"https://example.com".to_vec()),
            (SEEKING_SPEED_HANDLE, vec![0x00]),
            (PLAYING_ORDERS_SUPPORTED_HANDLE, vec![0x01, 0x00]),
            (MEDIA_STATE_HANDLE, vec![0x01]),
            (MEDIA_CONTROL_POINT_OPCODES_SUPPORTED_HANDLE, vec![0x01, 0x00, 0x00, 0x00]),
            (CONTENT_CONTROL_ID_HANDLE, vec![0x99]),
        ];

        for (handle, value) in read_only_writes {
            fake_gatt_server.incoming_write(peer, service_id, handle, 0, value);
            let poll_result = server.next().poll_unpin(&mut noop_cx);
            assert_matches!(poll_result, Poll::Pending);
            let FakeServerEvent::WriteResponded { value, .. } = event_receiver.try_recv().unwrap()
            else {
                panic!("expected WriteResponded for handle {:?}", handle);
            };
            assert_matches!(
                value.unwrap_err(),
                bt_gatt::types::Error::Gatt(GattError::WriteNotPermitted),
                "handle {:?} should return WriteNotPermitted on write",
                handle
            );
        }
    }

    #[test]
    fn control_point_unsupported_opcode_immediate_notification() {
        let peer = PeerId(1);
        let service_id = ServiceId::new(0x42);
        let (mut server, fake_gatt_server, mut event_receiver, mut noop_cx) =
            setup_test_server_with_control_point(peer);

        // Write an unsupported/RFU opcode (0xEE)
        fake_gatt_server.incoming_write(
            peer,
            service_id,
            MEDIA_CONTROL_POINT_HANDLE,
            0,
            vec![0xEE],
        );

        let poll_result = server.next().poll_unpin(&mut noop_cx);
        assert_matches!(poll_result, Poll::Pending);

        // ATT write is acknowledged
        let FakeServerEvent::WriteResponded { value, .. } = event_receiver.try_recv().unwrap()
        else {
            panic!("expected WriteResponded");
        };
        assert!(value.is_ok());

        // Immediate Media Control Point Notification sent with OPCODE_NOT_SUPPORTED
        // (0x02)
        let FakeServerEvent::Notified { handle, value, peers, .. } =
            event_receiver.try_recv().unwrap()
        else {
            panic!("expected Notified");
        };
        assert_eq!(handle, MEDIA_CONTROL_POINT_HANDLE);
        assert_eq!(peers, vec![peer]);
        assert_eq!(value, vec![0xEE, ControlPointResultCode::OpcodeNotSupported.into()]);
    }

    #[test]
    fn control_point_inactive_player_immediate_notification() {
        let peer = PeerId(1);
        let service_id = ServiceId::new(0x42);
        let (mut server, fake_gatt_server, mut event_receiver, mut noop_cx) =
            setup_test_server_with_control_point(peer);

        // Write Play opcode (0x01) while player is Inactive
        fake_gatt_server.incoming_write(
            peer,
            service_id,
            MEDIA_CONTROL_POINT_HANDLE,
            0,
            vec![0x01],
        );

        let poll_result = server.next().poll_unpin(&mut noop_cx);
        assert_matches!(poll_result, Poll::Pending);

        // ATT write is acknowledged
        let FakeServerEvent::WriteResponded { value, .. } = event_receiver.try_recv().unwrap()
        else {
            panic!("expected WriteResponded");
        };
        assert!(value.is_ok());

        // Immediate Media Control Point Notification sent with MEDIA_PLAYER_INACTIVE
        // (0x03)
        let FakeServerEvent::Notified { handle, value, peers, .. } =
            event_receiver.try_recv().unwrap()
        else {
            panic!("expected Notified");
        };
        assert_eq!(handle, MEDIA_CONTROL_POINT_HANDLE);
        assert_eq!(peers, vec![peer]);
        assert_eq!(value, vec![0x01, ControlPointResultCode::MediaPlayerInactive.into()]);
    }

    #[test]
    fn control_point_valid_command_success() {
        let peer = PeerId(1);
        let service_id = ServiceId::new(0x42);
        let (mut server, fake_gatt_server, mut event_receiver, mut noop_cx) =
            setup_test_server_with_control_point(peer);
        server.set_media_state(MediaState::Playing);

        // Write Pause opcode (0x02)
        fake_gatt_server.incoming_write(
            peer,
            service_id,
            MEDIA_CONTROL_POINT_HANDLE,
            0,
            vec![0x02],
        );

        let poll_result = server.next().poll_unpin(&mut noop_cx);
        let Poll::Ready(Some(Ok(McsServerEvent::ControlPointCommand { opcode, responder }))) =
            poll_result
        else {
            panic!("expected ControlPointCommand event, got {poll_result:?}");
        };
        assert_eq!(opcode, MediaControlOpcode::Pause);

        // ATT write is acknowledged
        let FakeServerEvent::WriteResponded { value, .. } = event_receiver.try_recv().unwrap()
        else {
            panic!("expected WriteResponded");
        };
        assert!(value.is_ok());

        // Upper layer executes command and responds with Success
        responder.send(ControlPointResultCode::Success);

        // Polling the server dispatches the notification
        let _ = server.next().poll_unpin(&mut noop_cx);

        let FakeServerEvent::Notified { handle, value, peers, .. } =
            event_receiver.try_recv().unwrap()
        else {
            panic!("expected Notified");
        };
        assert_eq!(handle, MEDIA_CONTROL_POINT_HANDLE);
        assert_eq!(peers, vec![peer]);
        assert_eq!(value, vec![0x02, ControlPointResultCode::Success.into()]);
    }

    #[test]
    fn control_point_parameterized_command_success() {
        let peer = PeerId(1);
        let service_id = ServiceId::new(0x42);
        let (mut server, fake_gatt_server, mut event_receiver, mut noop_cx) =
            setup_test_server_with_control_point(peer);
        server.set_media_state(MediaState::Playing);

        // MoveRelative opcode with 4-byte offset parameter
        let opcode = MediaControlOpcode::MoveRelative(1500);
        let mut write_val = vec![opcode.raw_opcode()];
        write_val.extend_from_slice(&1500i32.to_le_bytes());

        fake_gatt_server.incoming_write(peer, service_id, MEDIA_CONTROL_POINT_HANDLE, 0, write_val);

        let poll_result = server.next().poll_unpin(&mut noop_cx);
        let Poll::Ready(Some(Ok(McsServerEvent::ControlPointCommand {
            opcode: rx_opcode,
            responder,
        }))) = poll_result
        else {
            panic!("expected ControlPointCommand event, got {poll_result:?}");
        };
        assert_eq!(rx_opcode, opcode);

        let FakeServerEvent::WriteResponded { value, .. } = event_receiver.try_recv().unwrap()
        else {
            panic!("expected WriteResponded");
        };
        assert!(value.is_ok());

        responder.send(ControlPointResultCode::Success);
        let _ = server.next().poll_unpin(&mut noop_cx);

        let FakeServerEvent::Notified { handle, value, peers, .. } =
            event_receiver.try_recv().unwrap()
        else {
            panic!("expected Notified");
        };
        assert_eq!(handle, MEDIA_CONTROL_POINT_HANDLE);
        assert_eq!(peers, vec![peer]);
        assert_eq!(value, vec![opcode.raw_opcode(), ControlPointResultCode::Success.into()]);
    }

    #[test]
    fn control_point_truncated_parameter_sends_opcode_not_supported() {
        let peer = PeerId(1);
        let service_id = ServiceId::new(0x42);
        let (mut server, fake_gatt_server, mut event_receiver, mut noop_cx) =
            setup_test_server_with_control_point(peer);
        server.set_media_state(MediaState::Playing);

        // MoveRelative requires 5 octets; provide only 2 octets
        let raw_op = MediaControlOpcode::MoveRelative(0).raw_opcode();
        fake_gatt_server.incoming_write(
            peer,
            service_id,
            MEDIA_CONTROL_POINT_HANDLE,
            0,
            vec![raw_op, 0x01],
        );

        let poll_result = server.next().poll_unpin(&mut noop_cx);
        assert_matches!(poll_result, Poll::Pending);

        let FakeServerEvent::WriteResponded { value, .. } = event_receiver.try_recv().unwrap()
        else {
            panic!("expected WriteResponded");
        };
        assert!(value.is_ok());

        let FakeServerEvent::Notified { handle, value, peers, .. } =
            event_receiver.try_recv().unwrap()
        else {
            panic!("expected Notified");
        };
        assert_eq!(handle, MEDIA_CONTROL_POINT_HANDLE);
        assert_eq!(peers, vec![peer]);
        assert_eq!(value, vec![raw_op, ControlPointResultCode::OpcodeNotSupported.into()]);
    }

    #[test]
    fn control_point_empty_value_or_invalid_offset_returns_gatt_error() {
        let peer = PeerId(1);
        let service_id = ServiceId::new(0x42);
        let (mut server, fake_gatt_server, mut event_receiver, mut noop_cx) =
            setup_test_server_with_control_point(peer);

        // Non-zero offset returns InvalidOffset
        fake_gatt_server.incoming_write(
            peer,
            service_id,
            MEDIA_CONTROL_POINT_HANDLE,
            1,
            vec![0x01],
        );
        let poll_result = server.next().poll_unpin(&mut noop_cx);
        assert_matches!(poll_result, Poll::Pending);
        let FakeServerEvent::WriteResponded { value, .. } = event_receiver.try_recv().unwrap()
        else {
            panic!("expected WriteResponded");
        };
        assert_matches!(value.unwrap_err(), bt_gatt::types::Error::Gatt(GattError::InvalidOffset));

        // Empty value returns InvalidAttributeValueLength
        fake_gatt_server.incoming_write(peer, service_id, MEDIA_CONTROL_POINT_HANDLE, 0, vec![]);
        let poll_result = server.next().poll_unpin(&mut noop_cx);
        assert_matches!(poll_result, Poll::Pending);
        let FakeServerEvent::WriteResponded { value, .. } = event_receiver.try_recv().unwrap()
        else {
            panic!("expected WriteResponded");
        };
        assert_matches!(
            value.unwrap_err(),
            bt_gatt::types::Error::Gatt(GattError::InvalidAttributeValueLength)
        );
    }

    #[test]
    fn control_point_unsupported_opcode_on_active_player_returns_opcode_not_supported() {
        let peer = PeerId(1);
        let service_id = ServiceId::new(0x42);
        let (mut server, fake_gatt_server, mut event_receiver, mut noop_cx) =
            setup_test_server_with_control_point(peer);
        server.set_media_state(MediaState::Playing);
        server.set_supported_opcodes(SupportedOpcodes::PLAY);

        // Pause is valid in spec, but not in supported_opcodes for this server instance
        fake_gatt_server.incoming_write(
            peer,
            service_id,
            MEDIA_CONTROL_POINT_HANDLE,
            0,
            vec![MediaControlOpcode::Pause.raw_opcode()],
        );

        let poll_result = server.next().poll_unpin(&mut noop_cx);
        assert_matches!(poll_result, Poll::Pending);

        let FakeServerEvent::WriteResponded { value, .. } = event_receiver.try_recv().unwrap()
        else {
            panic!("expected WriteResponded");
        };
        assert!(value.is_ok());

        let FakeServerEvent::Notified { handle, value, peers, .. } =
            event_receiver.try_recv().unwrap()
        else {
            panic!("expected Notified");
        };
        assert_eq!(handle, MEDIA_CONTROL_POINT_HANDLE);
        assert_eq!(peers, vec![peer]);
        assert_eq!(
            value,
            vec![
                MediaControlOpcode::Pause.raw_opcode(),
                ControlPointResultCode::OpcodeNotSupported.into()
            ]
        );
    }

    #[test]
    fn control_point_dropped_responder_sends_cannot_be_completed() {
        let peer = PeerId(1);
        let service_id = ServiceId::new(0x42);
        let (mut server, fake_gatt_server, mut event_receiver, mut noop_cx) =
            setup_test_server_with_control_point(peer);
        server.set_media_state(MediaState::Playing);

        // Write Stop opcode (0x05)
        fake_gatt_server.incoming_write(
            peer,
            service_id,
            MEDIA_CONTROL_POINT_HANDLE,
            0,
            vec![0x05],
        );

        let poll_result = server.next().poll_unpin(&mut noop_cx);
        let Poll::Ready(Some(Ok(McsServerEvent::ControlPointCommand { opcode, responder }))) =
            poll_result
        else {
            panic!("expected ControlPointCommand event, got {poll_result:?}");
        };
        assert_eq!(opcode, MediaControlOpcode::Stop);

        // ATT write is acknowledged
        let FakeServerEvent::WriteResponded { value, .. } = event_receiver.try_recv().unwrap()
        else {
            panic!("expected WriteResponded");
        };
        assert!(value.is_ok());

        // Responder is dropped without calling send
        drop(responder);

        // Polling the server dispatches the fallback notification
        let _ = server.next().poll_unpin(&mut noop_cx);

        let FakeServerEvent::Notified { handle, value, peers, .. } =
            event_receiver.try_recv().unwrap()
        else {
            panic!("expected Notified");
        };
        assert_eq!(handle, MEDIA_CONTROL_POINT_HANDLE);
        assert_eq!(peers, vec![peer]);
        assert_eq!(value, vec![0x05, ControlPointResultCode::CommandCannotBeCompleted.into()]);
    }

    #[test]
    fn control_point_multiple_consecutive_notifications() {
        let peer1 = PeerId(1);
        let peer2 = PeerId(2);
        let service_id = ServiceId::new(0x42);
        let (mut server, fake_gatt_server, mut event_receiver, mut noop_cx) =
            setup_test_server_with_control_point(peer1);
        server.set_media_state(MediaState::Playing);

        // Also configure notifications for peer2
        fake_gatt_server.incoming_client_configuration(
            peer2,
            server.service_def.id(),
            MEDIA_CONTROL_POINT_HANDLE,
            bt_gatt::server::NotificationType::Notify,
        );
        let _ = server.next().poll_unpin(&mut noop_cx);
        let _ = event_receiver.try_recv();

        // Issue 1st command (Play from peer1)
        fake_gatt_server.incoming_write(
            peer1,
            service_id,
            MEDIA_CONTROL_POINT_HANDLE,
            0,
            vec![MediaControlOpcode::Play.raw_opcode()],
        );

        let poll_result = server.next().poll_unpin(&mut noop_cx);
        let Poll::Ready(Some(Ok(McsServerEvent::ControlPointCommand {
            opcode: op1,
            responder: resp1,
        }))) = poll_result
        else {
            panic!("expected 1st ControlPointCommand event, got {poll_result:?}");
        };
        assert_eq!(op1, MediaControlOpcode::Play);

        // Issue 2nd command (NextTrack from peer2)
        fake_gatt_server.incoming_write(
            peer2,
            service_id,
            MEDIA_CONTROL_POINT_HANDLE,
            0,
            vec![MediaControlOpcode::NextTrack.raw_opcode()],
        );

        let poll_result = server.next().poll_unpin(&mut noop_cx);
        let Poll::Ready(Some(Ok(McsServerEvent::ControlPointCommand {
            opcode: op2,
            responder: resp2,
        }))) = poll_result
        else {
            panic!("expected 2nd ControlPointCommand event, got {poll_result:?}");
        };
        assert_eq!(op2, MediaControlOpcode::NextTrack);

        // Drain write acknowledgements
        let FakeServerEvent::WriteResponded { value: val1, .. } =
            event_receiver.try_recv().unwrap()
        else {
            panic!("expected 1st WriteResponded");
        };
        assert!(val1.is_ok());

        let FakeServerEvent::WriteResponded { value: val2, .. } =
            event_receiver.try_recv().unwrap()
        else {
            panic!("expected 2nd WriteResponded");
        };
        assert!(val2.is_ok());

        // Respond to both commands in a row before polling the stream
        resp1.send(ControlPointResultCode::Success);
        resp2.send(ControlPointResultCode::CommandCannotBeCompleted);

        // Polling the server stream drains both pending control point responses and
        // issues two local service notifications in a single poll_next invocation.
        let poll_result = server.next().poll_unpin(&mut noop_cx);
        assert_matches!(poll_result, Poll::Pending);

        let n1 = event_receiver.try_recv().unwrap();
        let n2 = event_receiver.try_recv().unwrap();

        let mut received = Vec::new();
        for event in [n1, n2] {
            let FakeServerEvent::Notified { handle, value, peers, .. } = event else {
                panic!("expected Notified event, got {event:?}");
            };
            assert_eq!(handle, MEDIA_CONTROL_POINT_HANDLE);
            received.push((peers, value));
        }

        assert!(received.contains(&(
            vec![peer1],
            vec![MediaControlOpcode::Play.raw_opcode(), ControlPointResultCode::Success.into()]
        )));
        assert!(received.contains(&(
            vec![peer2],
            vec![
                MediaControlOpcode::NextTrack.raw_opcode(),
                ControlPointResultCode::CommandCannotBeCompleted.into()
            ]
        )));

        // No further events pending
        assert_matches!(event_receiver.try_recv(), Err(_));
    }

    #[test]
    fn server_stream_drains_pending_control_point_responses_before_terminating() {
        let peer = PeerId(1);
        let service_id = ServiceId::new(0x42);
        let (mut server, fake_gatt_server, mut event_receiver, mut noop_cx) =
            setup_test_server_with_control_point(peer);
        server.set_media_state(MediaState::Playing);

        // Write Pause opcode (0x02)
        fake_gatt_server.incoming_write(
            peer,
            service_id,
            MEDIA_CONTROL_POINT_HANDLE,
            0,
            vec![0x02],
        );

        let poll_result = server.next().poll_unpin(&mut noop_cx);
        let Poll::Ready(Some(Ok(McsServerEvent::ControlPointCommand { opcode, responder }))) =
            poll_result
        else {
            panic!("expected ControlPointCommand event, got {poll_result:?}");
        };
        assert_eq!(opcode, MediaControlOpcode::Pause);

        // ATT write is acknowledged
        let FakeServerEvent::WriteResponded { value, .. } = event_receiver.try_recv().unwrap()
        else {
            panic!("expected WriteResponded");
        };
        assert!(value.is_ok());

        // Replace local_service events stream with a custom channel and close it.
        let (sender, receiver) = futures::channel::mpsc::unbounded();
        let LocalServiceState::Published { service, .. } =
            std::mem::replace(&mut server.local_service, LocalServiceState::Terminated)
        else {
            panic!("Expected server to be in Published state");
        };
        server.local_service = LocalServiceState::Published { service, events: receiver };
        drop(sender);

        // Polling the server returns Pending because there is still an in-flight
        // responder
        let poll_result = server.next().poll_unpin(&mut noop_cx);
        assert_matches!(poll_result, Poll::Pending);

        // Upper layer executes command and responds with Success
        responder.send(ControlPointResultCode::Success);

        // Polling the server dispatches the notification and drains the in-flight
        // response, then terminates the stream as the GATT service event stream
        // has closed.
        let poll_result = server.next().poll_unpin(&mut noop_cx);
        assert_matches!(poll_result, Poll::Ready(None));

        let FakeServerEvent::Notified { handle, value, peers, .. } =
            event_receiver.try_recv().unwrap()
        else {
            panic!("expected Notified");
        };
        assert_eq!(handle, MEDIA_CONTROL_POINT_HANDLE);
        assert_eq!(peers, vec![peer]);
        assert_eq!(value, vec![0x02, ControlPointResultCode::Success.into()]);
    }

    #[test]
    fn write_negative_track_position_success() {
        let (mut server, fake_gatt_server, mut event_receiver) =
            setup_test_server(McsServerBuilder::generic(0x42, "Test Player"));
        server.state.media_state = MediaState::Paused;
        let mut noop_cx = Context::from_waker(futures::task::noop_waker_ref());

        let peer = PeerId(1);
        let service_id = ServiceId::new(0x42);

        fake_gatt_server.incoming_client_configuration(
            peer,
            service_id,
            TRACK_POSITION_HANDLE,
            bt_gatt::server::NotificationType::Notify,
        );
        let _ = server.next().poll_unpin(&mut noop_cx);
        let _ = event_receiver.try_recv();

        // Negative value represents offset from end of track per MCS v1.0.1 Section
        // 3.7.1
        fake_gatt_server.incoming_write(
            peer,
            service_id,
            TRACK_POSITION_HANDLE,
            0,
            (-500i32).to_le_bytes().to_vec(),
        );

        let poll_result = server.next().poll_unpin(&mut noop_cx);
        let Poll::Ready(Some(Ok(McsServerEvent::SetTrackPosition {
            peer_id,
            position,
            responder,
        }))) = poll_result
        else {
            panic!("expected SetTrackPosition event, got {poll_result:?}");
        };
        assert_eq!(peer_id, peer);
        assert_eq!(position, TrackPosition::from_raw_10ms(-500));

        let FakeServerEvent::WriteResponded { value, .. } = event_receiver.try_recv().unwrap()
        else {
            panic!("expected WriteResponded");
        };
        assert!(value.is_ok());

        // Upper layer confirms the updated track position
        responder.send(position);
        let _ = server.next().poll_unpin(&mut noop_cx);

        let FakeServerEvent::Notified { handle, value, peers, .. } =
            event_receiver.try_recv().unwrap()
        else {
            panic!("expected Notified");
        };
        assert_eq!(handle, TRACK_POSITION_HANDLE);
        assert_eq!(peers, vec![peer]);
        assert_eq!(value, (-500i32).to_le_bytes().to_vec());

        // Subsequent read reflects the updated track position
        fake_gatt_server.incoming_read(peer, service_id, TRACK_POSITION_HANDLE, 0);
        let _ = server.next().poll_unpin(&mut noop_cx);
        let FakeServerEvent::ReadResponded { value, .. } = event_receiver.try_recv().unwrap()
        else {
            panic!("expected ReadResponded");
        };
        assert_eq!(value.unwrap(), (-500i32).to_le_bytes());
    }

    #[test]
    fn write_responder_dropped_without_send_does_not_notify_or_mutate() {
        let (mut server, fake_gatt_server, mut event_receiver) = setup_test_server(
            McsServerBuilder::generic(0x42, "Test Player")
                .with_player_speeds()
                .with_playing_orders(SupportedPlayingOrders::all()),
        );
        let mut noop_cx = Context::from_waker(futures::task::noop_waker_ref());

        let peer = PeerId(1);
        let service_id = ServiceId::new(0x42);

        // 1. Playback speed write
        fake_gatt_server.incoming_write(peer, service_id, PLAYBACK_SPEED_HANDLE, 0, vec![0x40]);
        let poll_result = server.next().poll_unpin(&mut noop_cx);
        let Poll::Ready(Some(Ok(McsServerEvent::SetPlaybackSpeed { responder, .. }))) = poll_result
        else {
            panic!("expected SetPlaybackSpeed event, got {poll_result:?}");
        };
        // ATT write is acknowledged
        let FakeServerEvent::WriteResponded { value, .. } = event_receiver.try_recv().unwrap()
        else {
            panic!("expected WriteResponded");
        };
        assert!(value.is_ok());

        // Drop responder without calling send
        drop(responder);
        let poll_result = server.next().poll_unpin(&mut noop_cx);
        assert_matches!(poll_result, Poll::Pending);
        // No notification should be emitted
        assert_matches!(event_receiver.try_recv(), Err(_));

        // Playback speed remains unchanged
        fake_gatt_server.incoming_read(peer, service_id, PLAYBACK_SPEED_HANDLE, 0);
        let _ = server.next().poll_unpin(&mut noop_cx);
        let FakeServerEvent::ReadResponded { value, .. } = event_receiver.try_recv().unwrap()
        else {
            panic!("expected ReadResponded");
        };
        assert_eq!(value.unwrap(), vec![PlaybackSpeed::NORMAL.into()]);

        // 2. Track position write
        fake_gatt_server.incoming_write(
            peer,
            service_id,
            TRACK_POSITION_HANDLE,
            0,
            500i32.to_le_bytes().to_vec(),
        );
        let poll_result = server.next().poll_unpin(&mut noop_cx);
        let Poll::Ready(Some(Ok(McsServerEvent::SetTrackPosition { responder, .. }))) = poll_result
        else {
            panic!("expected SetTrackPosition event, got {poll_result:?}");
        };
        let FakeServerEvent::WriteResponded { value, .. } = event_receiver.try_recv().unwrap()
        else {
            panic!("expected WriteResponded");
        };
        assert!(value.is_ok());

        drop(responder);
        let poll_result = server.next().poll_unpin(&mut noop_cx);
        assert_matches!(poll_result, Poll::Pending);
        assert_matches!(event_receiver.try_recv(), Err(_));

        // Track position remains unavailable
        fake_gatt_server.incoming_read(peer, service_id, TRACK_POSITION_HANDLE, 0);
        let _ = server.next().poll_unpin(&mut noop_cx);
        let FakeServerEvent::ReadResponded { value, .. } = event_receiver.try_recv().unwrap()
        else {
            panic!("expected ReadResponded");
        };
        assert_eq!(value.unwrap(), TrackPosition::Unavailable.raw_10ms().to_le_bytes());

        // 3. Playing order write
        fake_gatt_server.incoming_write(
            peer,
            service_id,
            PLAYING_ORDER_HANDLE,
            0,
            vec![PlayingOrder::ShuffleOnce.into()],
        );
        let poll_result = server.next().poll_unpin(&mut noop_cx);
        let Poll::Ready(Some(Ok(McsServerEvent::SetPlayingOrder { responder, .. }))) = poll_result
        else {
            panic!("expected SetPlayingOrder event, got {poll_result:?}");
        };
        let FakeServerEvent::WriteResponded { value, .. } = event_receiver.try_recv().unwrap()
        else {
            panic!("expected WriteResponded");
        };
        assert!(value.is_ok());

        drop(responder);
        let poll_result = server.next().poll_unpin(&mut noop_cx);
        assert_matches!(poll_result, Poll::Pending);
        assert_matches!(event_receiver.try_recv(), Err(_));

        // Playing order remains default InOrderOnce
        fake_gatt_server.incoming_read(peer, service_id, PLAYING_ORDER_HANDLE, 0);
        let _ = server.next().poll_unpin(&mut noop_cx);
        let FakeServerEvent::ReadResponded { value, .. } = event_receiver.try_recv().unwrap()
        else {
            panic!("expected ReadResponded");
        };
        assert_eq!(value.unwrap(), vec![PlayingOrder::InOrderOnce.into()]);
    }

    #[test]
    fn write_playing_order_invalid_value_is_ignored() {
        let (mut server, fake_gatt_server, mut event_receiver) = setup_test_server(
            McsServerBuilder::generic(0x42, "Test Player")
                .with_playing_orders(SupportedPlayingOrders::all()),
        );
        let mut noop_cx = Context::from_waker(futures::task::noop_waker_ref());

        let peer = PeerId(1);
        let service_id = ServiceId::new(0x42);

        // Write an out-of-range RFU value (0xFF)
        fake_gatt_server.incoming_write(peer, service_id, PLAYING_ORDER_HANDLE, 0, vec![0xFF]);

        let poll_result = server.next().poll_unpin(&mut noop_cx);
        assert_matches!(poll_result, Poll::Pending);

        let FakeServerEvent::WriteResponded { value, .. } = event_receiver.try_recv().unwrap()
        else {
            panic!("expected WriteResponded");
        };
        assert!(value.is_ok());

        // Value remains unchanged (default InOrderOnce)
        fake_gatt_server.incoming_read(peer, service_id, PLAYING_ORDER_HANDLE, 0);
        let _ = server.next().poll_unpin(&mut noop_cx);
        let FakeServerEvent::ReadResponded { value, .. } = event_receiver.try_recv().unwrap()
        else {
            panic!("expected ReadResponded");
        };
        assert_eq!(value.unwrap(), vec![PlayingOrder::InOrderOnce.into()]);
    }

    #[test]
    fn local_state_handle_read() {
        let mut state = McsLocalState::new(0x01, "Player");
        state.media_state = MediaState::Paused;
        state.playback_speed = Some(PlaybackSpeed::NORMAL);
        state.playing_orders = Some(PlayingOrderState::new(SupportedPlayingOrders::all()));

        // Track Position
        assert_eq!(
            state.handle_read(TRACK_POSITION_HANDLE, 0),
            Ok(TrackPosition::Unavailable.raw_10ms().to_le_bytes().to_vec())
        );

        // Playback Speed
        assert_eq!(state.handle_read(PLAYBACK_SPEED_HANDLE, 0), Ok(vec![0x00]));

        // Playing Order
        assert_eq!(
            state.handle_read(PLAYING_ORDER_HANDLE, 0),
            Ok(vec![PlayingOrder::InOrderOnce.into()])
        );
    }

    #[test]
    fn playing_order_state_helpers() {
        let mut state = PlayingOrderState::new(SupportedPlayingOrders::IN_ORDER_ONCE);
        assert_eq!(state.current, PlayingOrder::InOrderOnce);
        assert_eq!(state.supported, SupportedPlayingOrders::IN_ORDER_ONCE);
        assert!(!state.set_order(PlayingOrder::SingleOnce));
        assert_eq!(state.current, PlayingOrder::InOrderOnce);
        assert!(state.set_order(PlayingOrder::InOrderOnce));

        let mut all_state = PlayingOrderState::new(SupportedPlayingOrders::all());
        assert_eq!(all_state.current, PlayingOrder::InOrderOnce);
        assert_eq!(all_state.supported, SupportedPlayingOrders::all());
        assert!(all_state.set_order(PlayingOrder::ShuffleRepeat));
        assert_eq!(all_state.current, PlayingOrder::ShuffleRepeat);
    }

    #[test]
    fn local_state_track_position_calculation() {
        let mut state = McsLocalState::new(0x01, "Test Player");

        // When no track is loaded, position is Unavailable regardless of state.
        assert_eq!(state.current_track_position(), TrackPosition::Unavailable);
        state.media_state = MediaState::Playing;
        assert_eq!(state.current_track_position(), TrackPosition::Unavailable);

        // When paused or seeking with a loaded track, position does not advance with
        // time.
        state.media_state = MediaState::Paused;
        state.track_position = TrackPosition::from_start(std::time::Duration::from_millis(5000));
        state.position_updated_at =
            Some(std::time::Instant::now() - std::time::Duration::from_secs(10));
        assert_eq!(
            state.current_track_position(),
            TrackPosition::from_start(std::time::Duration::from_millis(5000))
        );
        state.media_state = MediaState::Seeking;
        assert_eq!(
            state.current_track_position(),
            TrackPosition::from_start(std::time::Duration::from_millis(5000))
        );

        // When playing with a loaded track (FromStart), position advances based on
        // elapsed time.
        state.media_state = MediaState::Playing;
        state.track_duration = TrackDuration::from_duration(std::time::Duration::from_secs(20));
        state.track_position = TrackPosition::from_start(std::time::Duration::from_millis(5000));
        state.position_updated_at =
            Some(std::time::Instant::now() - std::time::Duration::from_millis(500));
        let computed = state.current_track_position();
        let TrackPosition::FromStart(dur) = computed else {
            panic!("expected FromStart");
        };
        assert!(
            dur >= std::time::Duration::from_millis(5450)
                && dur <= std::time::Duration::from_millis(5650),
            "unexpected computed position: {dur:?}"
        );

        // When elapsed time exceeds track duration, position is clamped to duration.
        state.position_updated_at =
            Some(std::time::Instant::now() - std::time::Duration::from_secs(100));
        assert_eq!(
            state.current_track_position(),
            TrackPosition::from_start(std::time::Duration::from_secs(20))
        );

        // When playing with a track position relative to end (FromEnd), base is
        // duration - offset.
        state.track_duration = TrackDuration::from_duration(std::time::Duration::from_secs(30));
        state.track_position = TrackPosition::from_end(std::time::Duration::from_secs(10));
        state.position_updated_at =
            Some(std::time::Instant::now() - std::time::Duration::from_millis(500));
        // Base is 30s - 10s = 20s. Elapsed 500ms -> ~20.5s from start.
        let computed = state.current_track_position();
        let TrackPosition::FromStart(dur) = computed else {
            panic!("expected FromStart");
        };
        assert!(
            dur >= std::time::Duration::from_millis(20450)
                && dur <= std::time::Duration::from_millis(20650),
            "unexpected computed position: {dur:?}"
        );

        // When FromEnd elapsed time exceeds track duration, position is clamped to
        // duration.
        state.position_updated_at =
            Some(std::time::Instant::now() - std::time::Duration::from_secs(100));
        assert_eq!(
            state.current_track_position(),
            TrackPosition::from_start(std::time::Duration::from_secs(30))
        );

        // When FromEnd is used with unknown duration, it cannot resolve to FromStart
        // and returns FromEnd.
        state.track_duration = TrackDuration::Unknown;
        state.track_position = TrackPosition::from_end(std::time::Duration::from_secs(10));
        assert_eq!(
            state.current_track_position(),
            TrackPosition::from_end(std::time::Duration::from_secs(10))
        );
    }

    #[test]
    fn read_track_position_during_active_playback() {
        let (mut server, fake_gatt_server, mut event_receiver) =
            setup_test_server(McsServerBuilder::generic(0x42, "Test Player"));

        // Set server state to Playing with a loaded track at position 500 (5.0
        // seconds).
        server.state.media_state = MediaState::Playing;
        server.state.track_duration =
            TrackDuration::from_duration(std::time::Duration::from_secs(60));
        server.state.track_position =
            TrackPosition::from_start(std::time::Duration::from_millis(5000));
        server.state.position_updated_at =
            Some(std::time::Instant::now() - std::time::Duration::from_millis(1000));

        let mut noop_cx = Context::from_waker(futures::task::noop_waker_ref());
        let peer = PeerId(1);
        let service_id = server.service_def.id();
        fake_gatt_server.incoming_read(peer, service_id, TRACK_POSITION_HANDLE, 0);
        let _ = server.next().poll_unpin(&mut noop_cx);
        let bt_gatt::test_utils::FakeServerEvent::ReadResponded { value, .. } =
            event_receiver.try_recv().unwrap()
        else {
            panic!("expected ReadResponded");
        };

        let raw_bytes = value.unwrap();
        assert_eq!(raw_bytes.len(), 4);
        let raw_10ms = i32::from_le_bytes(raw_bytes.try_into().unwrap());
        // 5000ms + 1000ms elapsed = 6000ms = 600 units of 10ms (allow minor jitter +/-
        // 30 units)
        assert!(raw_10ms >= 580 && raw_10ms <= 640, "unexpected raw_10ms: {raw_10ms}");
    }
}
