// 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::{
    CharacteristicProperties, CharacteristicProperty, GattError, Handle, ServiceKind,
};
use futures::stream::{FuturesUnordered, Stream};
use pin_project::pin_project;
use std::future::Future;
use std::task::{Context, Poll, Waker};

pub mod event;
use event::*;
pub use event::{
    ControlPointWriteResponder, McsServerEvent, SetPlaybackSpeedResponder,
    SetPlayingOrderResponder, SetTrackPositionResponder, SetValueResponder,
};

mod state;
use state::*;

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

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

/// 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 bt_gatt::Characteristic;
    use futures::{FutureExt, 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));
    }

    #[track_caller]
    fn expect_service_event(
        events: &mut futures::channel::mpsc::UnboundedReceiver<FakeServerEvent>,
    ) -> FakeServerEvent {
        let mut cx = Context::from_waker(futures::task::noop_waker_ref());
        match events.poll_next_unpin(&mut cx) {
            Poll::Ready(Some(event)) => event,
            x => panic!("Expected fake server event, got {x:?}"),
        }
    }

    #[track_caller]
    fn expect_no_service_event(
        events: &mut futures::channel::mpsc::UnboundedReceiver<FakeServerEvent>,
    ) {
        let mut cx = Context::from_waker(futures::task::noop_waker_ref());
        assert_matches!(events.poll_next_unpin(&mut cx), Poll::Pending);
    }

    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!(
            expect_service_event(&mut event_receiver),
            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);
        expect_no_service_event(&mut event_receiver);
        (server, fake_gatt_server, event_receiver, noop_cx)
    }

    #[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, .. } =
                expect_service_event(&mut event_receiver)
            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 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);
        expect_no_service_event(&mut event_receiver);

        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, .. } =
            expect_service_event(&mut event_receiver)
        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, .. } =
            expect_service_event(&mut event_receiver)
        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, .. } =
            expect_service_event(&mut event_receiver)
        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, .. } =
            expect_service_event(&mut event_receiver)
        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, .. } =
            expect_service_event(&mut event_receiver)
        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);
        expect_no_service_event(&mut event_receiver);

        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, .. } =
            expect_service_event(&mut event_receiver)
        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, .. } =
            expect_service_event(&mut event_receiver)
        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, .. } =
            expect_service_event(&mut event_receiver)
        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, .. } =
            expect_service_event(&mut event_receiver)
        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, .. } =
            expect_service_event(&mut event_receiver)
        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);
        expect_no_service_event(&mut event_receiver);

        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, .. } =
            expect_service_event(&mut event_receiver)
        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, .. } =
            expect_service_event(&mut event_receiver)
        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, .. } =
            expect_service_event(&mut event_receiver)
        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, .. } =
            expect_service_event(&mut event_receiver)
        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, .. } =
            expect_service_event(&mut event_receiver)
        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, .. } =
                expect_service_event(&mut event_receiver)
            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, .. } =
            expect_service_event(&mut event_receiver)
        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, .. } =
            expect_service_event(&mut event_receiver)
        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, .. } =
            expect_service_event(&mut event_receiver)
        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, .. } =
            expect_service_event(&mut event_receiver)
        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, .. } =
            expect_service_event(&mut event_receiver)
        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, .. } =
            expect_service_event(&mut event_receiver)
        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, .. } =
            expect_service_event(&mut event_receiver)
        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, .. } =
            expect_service_event(&mut event_receiver)
        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, .. } =
            expect_service_event(&mut event_receiver)
        else {
            panic!("expected WriteResponded");
        };
        assert!(value.is_ok());

        let FakeServerEvent::Notified { handle, value, peers, .. } =
            expect_service_event(&mut event_receiver)
        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, .. } =
            expect_service_event(&mut event_receiver)
        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, .. } =
            expect_service_event(&mut event_receiver)
        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, .. } =
            expect_service_event(&mut event_receiver)
        else {
            panic!("expected WriteResponded");
        };
        assert!(value.is_ok());

        let FakeServerEvent::Notified { handle, value, peers, .. } =
            expect_service_event(&mut event_receiver)
        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, .. } =
            expect_service_event(&mut event_receiver)
        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, .. } =
            expect_service_event(&mut event_receiver)
        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);
        expect_no_service_event(&mut event_receiver);

        // 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, .. } =
            expect_service_event(&mut event_receiver)
        else {
            panic!("expected 1st WriteResponded");
        };
        assert!(val1.is_ok());

        let FakeServerEvent::WriteResponded { value: val2, .. } =
            expect_service_event(&mut event_receiver)
        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 = expect_service_event(&mut event_receiver);
        let n2 = expect_service_event(&mut event_receiver);

        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
        expect_no_service_event(&mut event_receiver);
    }

    #[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, .. } =
            expect_service_event(&mut event_receiver)
        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, .. } =
            expect_service_event(&mut event_receiver)
        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);
        expect_no_service_event(&mut event_receiver);

        // 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, .. } =
            expect_service_event(&mut event_receiver)
        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, .. } =
            expect_service_event(&mut event_receiver)
        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, .. } =
            expect_service_event(&mut event_receiver)
        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, .. } =
            expect_service_event(&mut event_receiver)
        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
        expect_no_service_event(&mut event_receiver);

        // 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, .. } =
            expect_service_event(&mut event_receiver)
        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, .. } =
            expect_service_event(&mut event_receiver)
        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);
        expect_no_service_event(&mut event_receiver);

        // 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, .. } =
            expect_service_event(&mut event_receiver)
        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, .. } =
            expect_service_event(&mut event_receiver)
        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);
        expect_no_service_event(&mut event_receiver);

        // 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, .. } =
            expect_service_event(&mut event_receiver)
        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, .. } =
            expect_service_event(&mut event_receiver)
        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, .. } =
            expect_service_event(&mut event_receiver)
        else {
            panic!("expected ReadResponded");
        };
        assert_eq!(value.unwrap(), vec![PlayingOrder::InOrderOnce.into()]);
    }
}
