// 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::Uuid;
use bt_gatt::server::{
    LocalService, ReadResponder, Server as _, ServiceDefinition, ServiceEvent, ServiceId,
};
use bt_gatt::types::{
    AttributePermissions, CharacteristicProperties, CharacteristicProperty, GattError, Handle,
    SecurityLevels, ServiceKind,
};
use bt_gatt::Characteristic;
use futures::stream::Stream;
use pin_project::pin_project;
use std::future::Future;
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 Playback Speed characteristic.
const PLAYBACK_SPEED_HANDLE: Handle = Handle(6);
/// Handle assigned to the Seeking Speed characteristic.
const SEEKING_SPEED_HANDLE: Handle = Handle(7);
/// Handle assigned to the Playing Order characteristic.
const PLAYING_ORDER_HANDLE: Handle = Handle(8);
/// Handle assigned to the Playing Orders Supported characteristic.
const PLAYING_ORDERS_SUPPORTED_HANDLE: Handle = Handle(9);
/// Handle assigned to the Media State characteristic.
const MEDIA_STATE_HANDLE: Handle = Handle(10);
/// Handle assigned to the Media Control Point characteristic.
const MEDIA_CONTROL_POINT_HANDLE: Handle = Handle(11);
/// Handle assigned to the Media Control Point Opcodes Supported characteristic.
const MEDIA_CONTROL_POINT_OPCODES_SUPPORTED_HANDLE: Handle = Handle(12);
/// Handle assigned to the Content Control ID (CCID) characteristic.
const CONTENT_CONTROL_ID_HANDLE: Handle = Handle(13);

/// All 13 mandatory characteristics defined in MCS v1.0.1 Section 3.
fn mandatory_characteristics() -> [Characteristic; 13] {
    [
        build_mandatory_characteristic(
            MEDIA_PLAYER_NAME_HANDLE,
            MEDIA_PLAYER_NAME_UUID,
            CharacteristicProperties::READ_NOTIFY,
        ),
        build_mandatory_characteristic(
            TRACK_CHANGED_HANDLE,
            TRACK_CHANGED_UUID,
            CharacteristicProperty::Notify,
        ),
        build_mandatory_characteristic(
            TRACK_TITLE_HANDLE,
            TRACK_TITLE_UUID,
            CharacteristicProperties::READ_NOTIFY,
        ),
        build_mandatory_characteristic(
            TRACK_DURATION_HANDLE,
            TRACK_DURATION_UUID,
            CharacteristicProperties::READ_NOTIFY,
        ),
        build_mandatory_characteristic(
            TRACK_POSITION_HANDLE,
            TRACK_POSITION_UUID,
            CharacteristicProperties::READ_WRITE_NOTIFY,
        ),
        build_mandatory_characteristic(
            PLAYBACK_SPEED_HANDLE,
            PLAYBACK_SPEED_UUID,
            CharacteristicProperties::READ_WRITE_NOTIFY,
        ),
        build_mandatory_characteristic(
            SEEKING_SPEED_HANDLE,
            SEEKING_SPEED_UUID,
            CharacteristicProperties::READ_NOTIFY,
        ),
        build_mandatory_characteristic(
            PLAYING_ORDER_HANDLE,
            PLAYING_ORDER_UUID,
            CharacteristicProperties::READ_WRITE_NOTIFY,
        ),
        build_mandatory_characteristic(
            PLAYING_ORDERS_SUPPORTED_HANDLE,
            PLAYING_ORDERS_SUPPORTED_UUID,
            CharacteristicProperty::Read,
        ),
        build_mandatory_characteristic(
            MEDIA_STATE_HANDLE,
            MEDIA_STATE_UUID,
            CharacteristicProperties::READ_NOTIFY,
        ),
        build_mandatory_characteristic(
            MEDIA_CONTROL_POINT_HANDLE,
            MEDIA_CONTROL_POINT_UUID,
            CharacteristicProperties::WRITE_NOTIFY,
        ),
        build_mandatory_characteristic(
            MEDIA_CONTROL_POINT_OPCODES_SUPPORTED_HANDLE,
            MEDIA_CONTROL_POINT_OPCODES_SUPPORTED_UUID,
            CharacteristicProperties::READ_NOTIFY,
        ),
        build_mandatory_characteristic(
            CONTENT_CONTROL_ID_HANDLE,
            CONTENT_CONTROL_ID_UUID,
            CharacteristicProperty::Read,
        ),
    ]
}

/// Specification of a mandatory GATT characteristic for MCS.
/// Constructs a characteristic definition with the specified handle, UUID,
/// properties, and encryption-required permissions conforming to MCS v1.0.1
/// Section 3.
fn build_mandatory_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 { .. })
    }
}

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))));
                        }
                        None => {
                            self.as_mut().set(LocalServiceState::Terminated);
                            return Poll::Ready(None);
                        }
                    }
                }
            }
        }
    }
}

/// Local state of the mandatory 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,
}

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

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

    /// Reads the characteristic bytes for `handle` at `offset`.
    fn handle_read(&self, handle: Handle, offset: usize) -> Result<Vec<u8>, GattError> {
        // Track Changed is notify-only. Return Error. See MCS v1.0.1 Section 3.4.
        if handle == TRACK_CHANGED_HANDLE {
            return Err(GattError::ReadNotPermitted);
        }

        let read_at_offset =
            |bytes: &[u8]| bytes.get(offset..).map(Vec::from).ok_or(GattError::InvalidOffset);
        match handle {
            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]),
            _ => 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) }
    }

    /// Constructs the complete GATT [`ServiceDefinition`] containing all 13
    /// Mandatory Characteristics defined in MCS v1.0.1 Section 3.
    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)?;
        }

        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 { service_def, local_service: Default::default(), state: self.state })
    }
}

/// An instance of a Media Control Service (MCS) or Generic Media Control
/// Service (GMCS) GATT server.
#[pin_project]
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,
}

impl<T: bt_gatt::ServerTypes> McsServer<T> {
    /// 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(())
    }

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

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

    fn poll_next(
        mut self: std::pin::Pin<&mut Self>,
        cx: &mut Context<'_>,
    ) -> Poll<Option<Self::Item>> {
        loop {
            let gatt_event =
                match futures::ready!(self.as_mut().project().local_service.poll_next(cx)) {
                    None => return Poll::Ready(None),
                    Some(Err(e)) => return Poll::Ready(Some(Err(e))),
                    Some(Ok(event)) => event,
                };
            match gatt_event {
                ServiceEvent::Read { peer_id: _, handle, offset, responder } => {
                    self.handle_read(handle, offset as usize, responder);
                }
                // TODO(b/540400364): Add support for characteristic writes
                _ => continue,
            }
        }
    }
}

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

    use bt_common::PeerId;
    use bt_gatt::test_utils::{FakeServer, FakeServerEvent, FakeTypes};
    use bt_gatt::types::GattError;
    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("generic 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(), 13);
    }

    #[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(), 13);
    }

    #[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::instance(0x05, "Player 2");
        let builder3 = McsServerBuilder::instance(0x06, "Player 3");

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

        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 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 (0x2B93)
        assert_read_characteristic(
            &mut server,
            &fake_gatt_server,
            &mut event_receiver,
            MEDIA_PLAYER_NAME_HANDLE,
            b"Test Player",
        );

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

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

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

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

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

    #[test]
    fn read_string_characteristics_with_offset() {
        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, "Long Player Name"));

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

        // Valid offset slice
        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");

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

    #[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"));

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

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

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