// 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 Media State characteristic.
const MEDIA_STATE_HANDLE: Handle = Handle(6);
/// Handle assigned to the Content Control ID (CCID) characteristic.
const CONTENT_CONTROL_ID_HANDLE: Handle = Handle(7);

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    /// Reads the characteristic bytes for `handle` at `offset`.
    fn handle_read(&self, handle: Handle, offset: usize) -> Result<Vec<u8>, GattError> {
        let read_at_offset =
            |bytes: &[u8]| bytes.get(offset..).map(Vec::from).ok_or(GattError::InvalidOffset);
        match handle {
            // Track Changed and Media Control Point are not readable per MCS v1.0.1 Section 3,
            // Table 3.1.
            TRACK_CHANGED_HANDLE | MEDIA_CONTROL_POINT_HANDLE => Err(GattError::ReadNotPermitted),
            MEDIA_PLAYER_NAME_HANDLE => read_at_offset(self.player_name.as_bytes()),
            TRACK_TITLE_HANDLE => read_at_offset(self.track_title.as_bytes()),
            TRACK_DURATION_HANDLE => read_at_offset(&self.track_duration.raw_10ms().to_le_bytes()),
            TRACK_POSITION_HANDLE => {
                read_at_offset(&self.current_track_position().raw_10ms().to_le_bytes())
            }
            MEDIA_STATE_HANDLE => read_at_offset(&[self.media_state.into()]),
            CONTENT_CONTROL_ID_HANDLE => read_at_offset(&[self.ccid]),
            MEDIA_PLAYER_ICON_URL_HANDLE => {
                let url = self.icon_url.as_ref().ok_or(GattError::InvalidHandle)?;
                read_at_offset(url.as_bytes())
            }
            PLAYBACK_SPEED_HANDLE => {
                let speed = self.playback_speed.ok_or(GattError::InvalidHandle)?;
                read_at_offset(&[speed as u8])
            }
            SEEKING_SPEED_HANDLE => {
                let speed = self.seeking_speed.ok_or(GattError::InvalidHandle)?;
                read_at_offset(&[speed as u8])
            }
            PLAYING_ORDER_HANDLE => {
                let orders = self.playing_orders.as_ref().ok_or(GattError::InvalidHandle)?;
                read_at_offset(&[orders.current.into()])
            }
            PLAYING_ORDERS_SUPPORTED_HANDLE => {
                let orders = self.playing_orders.as_ref().ok_or(GattError::InvalidHandle)?;
                read_at_offset(&orders.supported.bits().to_le_bytes())
            }
            MEDIA_CONTROL_POINT_OPCODES_SUPPORTED_HANDLE => {
                let opcodes = self.supported_opcodes.ok_or(GattError::InvalidHandle)?;
                read_at_offset(&opcodes.bits().to_le_bytes())
            }
            _ => Err(GattError::InvalidHandle),
        }
    }
}

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

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

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

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

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

    /// Enables playback and seeking speed support with default speeds.
    pub fn with_player_speeds(mut self) -> Self {
        self.state.playback_speed = Some(0);
        self.state.seeking_speed = Some(0);
        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 { 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(), 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::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
        assert_read_characteristic(
            &mut server,
            &fake_gatt_server,
            &mut event_receiver,
            MEDIA_PLAYER_NAME_HANDLE,
            b"Test Player",
        );

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    #[test]
    fn 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}");
    }
}
