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

use std::sync::Arc;

use futures::stream::{SelectAll, StreamExt};
use parking_lot::Mutex;
use thiserror::Error;

use bt_common::packet_encoding::Decodable;
use bt_common::Uuid;
use bt_gatt::client::{PeerService, ServiceCharacteristic};
use bt_gatt::types::{CharacteristicProperty, Handle};

use crate::types::*;

pub mod event;

pub use event::{CsisNotification, NotificationStream};

#[derive(Debug, Error)]
pub enum Error {
    #[error("GATT operation error: {0}")]
    Gatt(#[from] bt_gatt::types::Error),

    #[error("Packet serialization/deserialization error: {0}")]
    Packet(#[from] bt_common::packet_encoding::Error),

    #[error("Missing required characteristic: {0}")]
    MissingCharacteristic(Uuid),

    #[error("Extra characteristic found: {0}")]
    ExtraCharacteristic(Uuid),

    #[error("Invalid characteristic value: {0}")]
    InvalidCharacteristic(String),

    #[error("Notification from unexpected characteristic handle: {0:?}")]
    UnexpectedNotification(Handle),
}

/// The values of the characteristics exposed by the CSIS service.
#[derive(Debug, Clone)]
pub(crate) struct CsisClientState {
    sirk: SetIdentityResolvingKey,
    size: Option<CoordinatedSetSize>,
    rank: Option<SetMemberRank>,
    lock_state: Option<SetMemberLock>,
}

impl CsisClientState {
    pub(crate) fn sirk(&self) -> SetIdentityResolvingKey {
        self.sirk
    }

    pub(crate) fn set_sirk(&mut self, sirk: SetIdentityResolvingKey) {
        self.sirk = sirk;
    }

    pub(crate) fn size(&self) -> Option<CoordinatedSetSize> {
        self.size
    }

    pub(crate) fn set_size(&mut self, size: CoordinatedSetSize) {
        self.size = Some(size);
    }

    pub(crate) fn rank(&self) -> Option<SetMemberRank> {
        self.rank
    }

    pub(crate) fn lock_state(&self) -> Option<SetMemberLock> {
        self.lock_state
    }

    pub(crate) fn set_lock_state(&mut self, lock_state: SetMemberLock) {
        self.lock_state = Some(lock_state);
    }
}

/// A GATT client for interacting with the Coordinated Set Identification
/// Service (CSIS). See CSIS v1.1 Section 2 & Section 5 and CSIP v1.1 Section
/// 4.2 & Section 4.3.
pub struct CoordinatedSetIdentificationServiceClient<T: bt_gatt::GattTypes> {
    // The connection to this CSIS service instance. Held to keep it, and the
    // notification subscriptions registered through it, alive.
    gatt_client: T::PeerService,
    sirk_handle: Handle,
    size_handle: Option<Handle>,
    lock_handle: Option<Handle>,
    /// Set Member Rank is not notifiable, so a change is only seen by
    /// re-reading.
    // TODO(b/534436497): implement re-reading.
    _rank_handle: Option<Handle>,

    /// Shared with the [`NotificationStream`] so that a value updated by a
    /// GATT notification is visible through this client's accessors.
    state: Arc<Mutex<CsisClientState>>,

    /// Handles of the notifiable characteristics. Taken by
    /// [`Self::take_notification_stream`].
    notifiable_handles: Option<Vec<Handle>>,
}

impl<T: bt_gatt::GattTypes> CoordinatedSetIdentificationServiceClient<T> {
    /// Discovers CSIS characteristics and reads their initial values. See CSIS
    /// v1.1 Section 5, Table 5.1 and CSIP v1.1 Section 4.3.
    ///
    /// Does not register for notifications; call
    /// [`Self::take_notification_stream`] to subscribe.
    pub async fn create(gatt_client: T::PeerService) -> Result<Self, Error> {
        let discovered = gatt_client.discover_characteristics(None).await?;

        let mut sirk = None;
        let mut size = None;
        let mut rank = None;
        let mut lock = None;

        let mut notifiable_handles = Vec::new();

        // The CSIS service exposes at most one of each characteristic.
        for ch in discovered {
            let chr = ServiceCharacteristic::new(&gatt_client, ch);
            let uuid = chr.uuid();
            let handle = *chr.handle();

            match uuid {
                SET_IDENTITY_RESOLVING_KEY_UUID => {
                    if sirk.is_some() {
                        return Err(Error::ExtraCharacteristic(uuid));
                    }
                    sirk = Some((handle, Self::read_sirk(&chr).await?));
                }
                COORDINATED_SET_SIZE_UUID => {
                    if size.is_some() {
                        return Err(Error::ExtraCharacteristic(uuid));
                    }
                    size = Some((handle, Self::read_size(&chr).await?));
                }
                SET_MEMBER_LOCK_UUID => {
                    if lock.is_some() {
                        return Err(Error::ExtraCharacteristic(uuid));
                    }
                    lock = Some((handle, Self::read_lock(&chr).await?));
                }
                SET_MEMBER_RANK_UUID => {
                    if rank.is_some() {
                        return Err(Error::ExtraCharacteristic(uuid));
                    }
                    rank = Some((handle, Self::read_rank(&chr).await?));
                }
                _ => continue,
            }

            if chr.characteristic().properties.contains(CharacteristicProperty::Notify) {
                notifiable_handles.push(handle);
            }
        }

        let (sirk_handle, sirk) =
            sirk.ok_or(Error::MissingCharacteristic(SET_IDENTITY_RESOLVING_KEY_UUID))?;
        let (size_handle, size) = size.unzip();
        let (rank_handle, rank) = rank.unzip();
        let (lock_handle, lock_state) = lock.unzip();

        if lock_handle.is_some() && rank_handle.is_none() {
            // CSIS v1.1 Section 5, Table 5.1 Note C.1: Mandatory if Set Member Lock is
            // supported
            return Err(Error::MissingCharacteristic(SET_MEMBER_RANK_UUID));
        }

        if let (Some(r), Some(s)) = (rank, size) {
            if r.0.get() > s.0.get() {
                return Err(Error::InvalidCharacteristic(
                    "SetMemberRank cannot be greater than CoordinatedSetSize".to_string(),
                ));
            }
        }

        Ok(Self {
            gatt_client,
            sirk_handle,
            size_handle,
            lock_handle,
            _rank_handle: rank_handle,
            state: Arc::new(Mutex::new(CsisClientState { sirk, size, rank, lock_state })),
            notifiable_handles: Some(notifiable_handles),
        })
    }

    // TODO(b/534436497): Implement FromCharacteristic for the CSIS value types
    // in place of these readers.
    async fn read_sirk(
        chr: &ServiceCharacteristic<'_, T>,
    ) -> Result<SetIdentityResolvingKey, Error> {
        let mut buf = [0; SetIdentityResolvingKey::BYTE_SIZE];
        let bytes_read = chr.read(&mut buf).await?;
        let (sirk_res, _) = SetIdentityResolvingKey::decode(&buf[..bytes_read]);
        Ok(sirk_res?)
    }

    async fn read_size(chr: &ServiceCharacteristic<'_, T>) -> Result<CoordinatedSetSize, Error> {
        let mut buf = [0; CoordinatedSetSize::BYTE_SIZE];
        let bytes_read = chr.read(&mut buf).await?;
        let (size_res, _) = CoordinatedSetSize::decode(&buf[..bytes_read]);
        Ok(size_res?)
    }

    async fn read_rank(chr: &ServiceCharacteristic<'_, T>) -> Result<SetMemberRank, Error> {
        let mut buf = [0; SetMemberRank::BYTE_SIZE];
        let bytes_read = chr.read(&mut buf).await?;
        let (rank_res, _) = SetMemberRank::decode(&buf[..bytes_read]);
        Ok(rank_res?)
    }

    async fn read_lock(chr: &ServiceCharacteristic<'_, T>) -> Result<SetMemberLock, Error> {
        // CSIS v1.1 Table 5.1: Notify is mandatory for Set Member Lock.
        if !chr.characteristic().properties.contains(CharacteristicProperty::Notify) {
            return Err(Error::InvalidCharacteristic(
                "Set Member Lock characteristic must support notifications".to_string(),
            ));
        }

        let mut buf = [0; SetMemberLock::BYTE_SIZE];
        let bytes_read = chr.read(&mut buf).await?;
        let (lock_res, _) = SetMemberLock::decode(&buf[..bytes_read]);
        Ok(lock_res?)
    }

    pub fn sirk(&self) -> SetIdentityResolvingKey {
        self.state.lock().sirk()
    }

    /// The last known value of the Coordinated Set Size characteristic, or
    /// `None` if the Set Member does not support it.
    pub fn size(&self) -> Option<CoordinatedSetSize> {
        self.state.lock().size()
    }

    /// The last known value of the Set Member Rank characteristic, or `None` if
    /// the Set Member does not support it.
    pub fn rank(&self) -> Option<SetMemberRank> {
        self.state.lock().rank()
    }

    /// The last known value of the Set Member Lock characteristic, or `None` if
    /// the Set Member does not support it.
    pub fn lock_state(&self) -> Option<SetMemberLock> {
        self.state.lock().lock_state()
    }

    /// Subscribes to the CSIS characteristics that support being notified and
    /// takes the stream of the value changes they report.
    ///
    /// The stream is only available once; subsequent calls return `None`. It
    /// yields no events if the Set Member does not support notifications on
    /// any CSIS characteristic.
    pub fn take_notification_stream(&mut self) -> Option<NotificationStream>
    where
        <T as bt_gatt::GattTypes>::NotificationStream: Send,
    {
        let handles = self.notifiable_handles.take()?;
        let mut notification_streams = SelectAll::new();
        for handle in handles {
            notification_streams.push(self.gatt_client.subscribe(&handle).boxed());
        }
        Some(NotificationStream::new(
            notification_streams,
            event::NotifiedHandles {
                sirk: self.sirk_handle,
                size: self.size_handle,
                lock: self.lock_handle,
            },
            self.state.clone(),
        ))
    }

    // TODO(b/534436497): Add lock() and unlock(). See CSIS v1.1 Section 5.3.1.
}

#[cfg(test)]
mod tests {
    use super::*;
    use assert_matches::assert_matches;
    use bt_gatt::test_utils::*;
    use bt_gatt::types::{AttributePermissions, CharacteristicProperty, Handle};
    use bt_gatt::Characteristic;
    use core::num::NonZeroU8;
    use futures::{
        pin_mut,
        task::{noop_waker_ref, Context, Poll},
        FutureExt,
    };

    const SIRK_HANDLE: Handle = Handle(1);
    const SIZE_HANDLE: Handle = Handle(2);
    const LOCK_HANDLE: Handle = Handle(3);
    const RANK_HANDLE: Handle = Handle(4);

    fn add_char(service: &mut FakePeerService, handle: Handle, uuid: Uuid, value: Vec<u8>) {
        service.add_characteristic(
            Characteristic {
                handle,
                uuid,
                properties: CharacteristicProperty::Read.into(),
                permissions: AttributePermissions::default(),
                descriptors: vec![],
            },
            value,
        );
    }

    /// Adds a Set Member Lock characteristic with Read, Write and Notify
    /// properties.
    fn add_lock_char(service: &mut FakePeerService, handle: Handle, value: Vec<u8>) {
        service.add_characteristic(
            Characteristic {
                handle,
                uuid: SET_MEMBER_LOCK_UUID,
                properties: (&[
                    CharacteristicProperty::Read,
                    CharacteristicProperty::Write,
                    CharacteristicProperty::Notify,
                ])
                    .into(),
                permissions: AttributePermissions::default(),
                descriptors: vec![],
            },
            value,
        );
    }

    #[test]
    fn create_success_all_chars() {
        let mut service = FakePeerService::new();
        let mut noop_cx = Context::from_waker(noop_waker_ref());

        // Valid SIRK: Type 1 (Plaintext) + 16 bytes key
        let mut sirk_val = vec![0x01];
        sirk_val.extend_from_slice(&[0xAB; 16]);
        add_char(&mut service, SIRK_HANDLE, SET_IDENTITY_RESOLVING_KEY_UUID, sirk_val);

        add_char(&mut service, SIZE_HANDLE, COORDINATED_SET_SIZE_UUID, vec![0x02]);
        add_lock_char(&mut service, LOCK_HANDLE, vec![0x01]); // 0x01 = Unlocked per CSIS v1.1 Section 5.3, Table 5.4
        add_char(&mut service, RANK_HANDLE, SET_MEMBER_RANK_UUID, vec![0x01]);

        let create_fut = CoordinatedSetIdentificationServiceClient::<FakeTypes>::create(service);
        pin_mut!(create_fut);
        let Poll::Ready(client) = create_fut.poll_unpin(&mut noop_cx) else {
            panic!("Expected create to be ready");
        };
        let client = client.unwrap();

        assert_eq!(client.sirk_handle, SIRK_HANDLE);
        assert_eq!(client.size_handle, Some(SIZE_HANDLE));
        assert_eq!(client.lock_handle, Some(LOCK_HANDLE));
        assert_eq!(client._rank_handle, Some(RANK_HANDLE));

        assert_eq!(client.sirk().sirk_type, SirkType::Plaintext);
        assert_eq!(client.size(), Some(CoordinatedSetSize(NonZeroU8::new(2).unwrap())));
        assert_eq!(client.rank(), Some(SetMemberRank(NonZeroU8::new(1).unwrap())));
        assert_eq!(client.lock_state(), Some(SetMemberLock::Unlocked));
    }

    #[test]
    fn create_success_only_mandatory() {
        let mut service = FakePeerService::new();
        let mut noop_cx = Context::from_waker(noop_waker_ref());

        let mut sirk_val = vec![0x01];
        sirk_val.extend_from_slice(&[0xAB; 16]);
        add_char(&mut service, SIRK_HANDLE, SET_IDENTITY_RESOLVING_KEY_UUID, sirk_val);

        let create_fut = CoordinatedSetIdentificationServiceClient::<FakeTypes>::create(service);
        pin_mut!(create_fut);
        let Poll::Ready(client) = create_fut.poll_unpin(&mut noop_cx) else {
            panic!("Expected create to be ready");
        };
        let client = client.unwrap();

        assert_eq!(client.sirk_handle, SIRK_HANDLE);
        assert_eq!(client.size_handle, None);
        assert_eq!(client.lock_handle, None);
        assert_eq!(client._rank_handle, None);
        assert_eq!(client.lock_state(), None);
    }

    #[test]
    fn create_success_rank_present_without_lock() {
        let mut service = FakePeerService::new();
        let mut noop_cx = Context::from_waker(noop_waker_ref());

        let mut sirk_val = vec![0x01];
        sirk_val.extend_from_slice(&[0xAB; 16]);
        add_char(&mut service, SIRK_HANDLE, SET_IDENTITY_RESOLVING_KEY_UUID, sirk_val);
        add_char(&mut service, RANK_HANDLE, SET_MEMBER_RANK_UUID, vec![0x01]);

        let create_fut = CoordinatedSetIdentificationServiceClient::<FakeTypes>::create(service);
        pin_mut!(create_fut);
        let Poll::Ready(client) = create_fut.poll_unpin(&mut noop_cx) else {
            panic!("Expected create to be ready");
        };
        let client = client.unwrap();

        assert_eq!(client.sirk_handle, SIRK_HANDLE);
        assert_eq!(client.size_handle, None);
        assert_eq!(client.lock_handle, None);
        assert_eq!(client._rank_handle, Some(RANK_HANDLE));
        assert_eq!(client.rank().unwrap().0.get(), 1);
    }

    #[test]
    fn create_fails_missing_sirk() {
        let service = FakePeerService::new();
        let mut noop_cx = Context::from_waker(noop_waker_ref());
        let create_fut = CoordinatedSetIdentificationServiceClient::<FakeTypes>::create(service);
        pin_mut!(create_fut);
        let Poll::Ready(result) = create_fut.poll_unpin(&mut noop_cx) else {
            panic!("Expected create to be ready");
        };
        assert!(result.is_err());
        assert_matches!(result.err().unwrap(), Error::MissingCharacteristic(uuid) if uuid == SET_IDENTITY_RESOLVING_KEY_UUID);
    }

    #[test]
    fn create_fails_duplicate_sirk() {
        let mut service = FakePeerService::new();
        let mut noop_cx = Context::from_waker(noop_waker_ref());

        let mut sirk_val = vec![0x01];
        sirk_val.extend_from_slice(&[0xAB; 16]);
        add_char(&mut service, SIRK_HANDLE, SET_IDENTITY_RESOLVING_KEY_UUID, sirk_val.clone());
        add_char(&mut service, Handle(5), SET_IDENTITY_RESOLVING_KEY_UUID, sirk_val);

        let create_fut = CoordinatedSetIdentificationServiceClient::<FakeTypes>::create(service);
        pin_mut!(create_fut);
        let Poll::Ready(result) = create_fut.poll_unpin(&mut noop_cx) else {
            panic!("Expected create to be ready");
        };
        assert!(result.is_err());
        assert_matches!(result.err().unwrap(), Error::ExtraCharacteristic(uuid) if uuid == SET_IDENTITY_RESOLVING_KEY_UUID);
    }

    #[test]
    fn create_fails_lock_present_rank_missing() {
        let mut service = FakePeerService::new();
        let mut noop_cx = Context::from_waker(noop_waker_ref());

        let mut sirk_val = vec![0x01];
        sirk_val.extend_from_slice(&[0xAB; 16]);
        add_char(&mut service, SIRK_HANDLE, SET_IDENTITY_RESOLVING_KEY_UUID, sirk_val);

        add_lock_char(&mut service, LOCK_HANDLE, vec![0x01]);
        // Missing Rank

        let create_fut = CoordinatedSetIdentificationServiceClient::<FakeTypes>::create(service);
        pin_mut!(create_fut);
        let Poll::Ready(result) = create_fut.poll_unpin(&mut noop_cx) else {
            panic!("Expected create to be ready");
        };
        assert!(result.is_err());
        assert_matches!(result.err().unwrap(), Error::MissingCharacteristic(uuid) if uuid == SET_MEMBER_RANK_UUID);
    }

    #[test]
    fn create_fails_invalid_size() {
        let mut service = FakePeerService::new();
        let mut noop_cx = Context::from_waker(noop_waker_ref());

        let mut sirk_val = vec![0x01];
        sirk_val.extend_from_slice(&[0xAB; 16]);
        add_char(&mut service, SIRK_HANDLE, SET_IDENTITY_RESOLVING_KEY_UUID, sirk_val);

        add_char(&mut service, SIZE_HANDLE, COORDINATED_SET_SIZE_UUID, vec![0x00]); // Invalid Size 0

        let create_fut = CoordinatedSetIdentificationServiceClient::<FakeTypes>::create(service);
        pin_mut!(create_fut);
        let Poll::Ready(result) = create_fut.poll_unpin(&mut noop_cx) else {
            panic!("Expected create to be ready");
        };
        assert!(result.is_err());
        assert_matches!(result.err().unwrap(), Error::Packet(_));
    }

    #[test]
    fn create_fails_invalid_rank_zero() {
        let mut service = FakePeerService::new();
        let mut noop_cx = Context::from_waker(noop_waker_ref());

        let mut sirk_val = vec![0x01];
        sirk_val.extend_from_slice(&[0xAB; 16]);
        add_char(&mut service, SIRK_HANDLE, SET_IDENTITY_RESOLVING_KEY_UUID, sirk_val);
        add_char(&mut service, RANK_HANDLE, SET_MEMBER_RANK_UUID, vec![0x00]); // Invalid Rank 0

        let create_fut = CoordinatedSetIdentificationServiceClient::<FakeTypes>::create(service);
        pin_mut!(create_fut);
        let Poll::Ready(result) = create_fut.poll_unpin(&mut noop_cx) else {
            panic!("Expected create to be ready");
        };
        assert!(result.is_err());
        assert_matches!(result.err().unwrap(), Error::Packet(_));
    }

    #[test]
    fn create_fails_rank_greater_than_size() {
        let mut service = FakePeerService::new();
        let mut noop_cx = Context::from_waker(noop_waker_ref());

        let mut sirk_val = vec![0x01];
        sirk_val.extend_from_slice(&[0xAB; 16]);
        add_char(&mut service, SIRK_HANDLE, SET_IDENTITY_RESOLVING_KEY_UUID, sirk_val);
        add_char(&mut service, SIZE_HANDLE, COORDINATED_SET_SIZE_UUID, vec![0x02]);
        add_char(&mut service, RANK_HANDLE, SET_MEMBER_RANK_UUID, vec![0x03]); // Rank 3 > Size 2

        let create_fut = CoordinatedSetIdentificationServiceClient::<FakeTypes>::create(service);
        pin_mut!(create_fut);
        let Poll::Ready(result) = create_fut.poll_unpin(&mut noop_cx) else {
            panic!("Expected create to be ready");
        };
        assert!(result.is_err());
        assert_matches!(result.err().unwrap(), Error::InvalidCharacteristic(_));
    }

    #[test]
    fn create_fails_duplicate_size() {
        let mut service = FakePeerService::new();
        let mut noop_cx = Context::from_waker(noop_waker_ref());

        let mut sirk_val = vec![0x01];
        sirk_val.extend_from_slice(&[0xAB; 16]);
        add_char(&mut service, SIRK_HANDLE, SET_IDENTITY_RESOLVING_KEY_UUID, sirk_val);

        add_char(&mut service, SIZE_HANDLE, COORDINATED_SET_SIZE_UUID, vec![0x02]);
        add_char(&mut service, Handle(5), COORDINATED_SET_SIZE_UUID, vec![0x03]); // Duplicate

        let create_fut = CoordinatedSetIdentificationServiceClient::<FakeTypes>::create(service);
        pin_mut!(create_fut);
        let Poll::Ready(result) = create_fut.poll_unpin(&mut noop_cx) else {
            panic!("Expected create to be ready");
        };
        assert!(result.is_err());
        assert_matches!(result.err().unwrap(), Error::ExtraCharacteristic(uuid) if uuid == COORDINATED_SET_SIZE_UUID);
    }

    #[test]
    fn create_fails_duplicate_lock() {
        let mut service = FakePeerService::new();
        let mut noop_cx = Context::from_waker(noop_waker_ref());

        let mut sirk_val = vec![0x01];
        sirk_val.extend_from_slice(&[0xAB; 16]);
        add_char(&mut service, SIRK_HANDLE, SET_IDENTITY_RESOLVING_KEY_UUID, sirk_val);

        add_lock_char(&mut service, LOCK_HANDLE, vec![0x01]);
        add_lock_char(&mut service, Handle(5), vec![0x01]); // Duplicate
        add_char(&mut service, RANK_HANDLE, SET_MEMBER_RANK_UUID, vec![0x01]); // Rank is mandatory if lock present per CSIS v1.1 Table 5.1 Note C.1

        let create_fut = CoordinatedSetIdentificationServiceClient::<FakeTypes>::create(service);
        pin_mut!(create_fut);
        let Poll::Ready(result) = create_fut.poll_unpin(&mut noop_cx) else {
            panic!("Expected create to be ready");
        };
        assert!(result.is_err());
        assert_matches!(result.err().unwrap(), Error::ExtraCharacteristic(uuid) if uuid == SET_MEMBER_LOCK_UUID);
    }

    #[test]
    fn create_fails_lock_without_notify() {
        let mut service = FakePeerService::new();
        let mut noop_cx = Context::from_waker(noop_waker_ref());

        let mut sirk_val = vec![0x01];
        sirk_val.extend_from_slice(&[0xAB; 16]);
        add_char(&mut service, SIRK_HANDLE, SET_IDENTITY_RESOLVING_KEY_UUID, sirk_val);

        // A Lock characteristic without the mandatory Notify property.
        add_char(&mut service, LOCK_HANDLE, SET_MEMBER_LOCK_UUID, vec![0x01]);
        add_char(&mut service, RANK_HANDLE, SET_MEMBER_RANK_UUID, vec![0x01]);

        let create_fut = CoordinatedSetIdentificationServiceClient::<FakeTypes>::create(service);
        pin_mut!(create_fut);
        let Poll::Ready(result) = create_fut.poll_unpin(&mut noop_cx) else {
            panic!("Expected create to be ready");
        };
        assert_matches!(result.err().unwrap(), Error::InvalidCharacteristic(_));
    }

    #[test]
    fn create_fails_duplicate_rank() {
        let mut service = FakePeerService::new();
        let mut noop_cx = Context::from_waker(noop_waker_ref());

        let mut sirk_val = vec![0x01];
        sirk_val.extend_from_slice(&[0xAB; 16]);
        add_char(&mut service, SIRK_HANDLE, SET_IDENTITY_RESOLVING_KEY_UUID, sirk_val);

        add_char(&mut service, RANK_HANDLE, SET_MEMBER_RANK_UUID, vec![0x01]);
        add_char(&mut service, Handle(5), SET_MEMBER_RANK_UUID, vec![0x02]); // Duplicate

        let create_fut = CoordinatedSetIdentificationServiceClient::<FakeTypes>::create(service);
        pin_mut!(create_fut);
        let Poll::Ready(result) = create_fut.poll_unpin(&mut noop_cx) else {
            panic!("Expected create to be ready");
        };
        assert!(result.is_err());
        assert_matches!(result.err().unwrap(), Error::ExtraCharacteristic(uuid) if uuid == SET_MEMBER_RANK_UUID);
    }

    #[test]
    fn create_fails_sirk_invalid_length() {
        let invalid_payloads = vec![
            vec![],        // Empty (0 bytes)
            vec![0x01; 5], // Too short (5 bytes < 17 bytes)
        ];

        for payload in invalid_payloads {
            let mut service = FakePeerService::new();
            let mut noop_cx = Context::from_waker(noop_waker_ref());
            add_char(&mut service, SIRK_HANDLE, SET_IDENTITY_RESOLVING_KEY_UUID, payload);

            let create_fut =
                CoordinatedSetIdentificationServiceClient::<FakeTypes>::create(service);
            pin_mut!(create_fut);
            let Poll::Ready(result) = create_fut.poll_unpin(&mut noop_cx) else {
                panic!("Expected create to be ready");
            };
            assert!(result.is_err());
            assert_matches!(
                result.err().unwrap(),
                Error::Packet(bt_common::packet_encoding::Error::UnexpectedDataLength)
            );
        }
    }

    #[test]
    fn create_fails_size_invalid_length() {
        let mut service = FakePeerService::new();
        let mut noop_cx = Context::from_waker(noop_waker_ref());

        let mut sirk_val = vec![0x01];
        sirk_val.extend_from_slice(&[0xAB; 16]);
        add_char(&mut service, SIRK_HANDLE, SET_IDENTITY_RESOLVING_KEY_UUID, sirk_val);
        add_char(&mut service, SIZE_HANDLE, COORDINATED_SET_SIZE_UUID, vec![]); // Empty (0 bytes)

        let create_fut = CoordinatedSetIdentificationServiceClient::<FakeTypes>::create(service);
        pin_mut!(create_fut);
        let Poll::Ready(result) = create_fut.poll_unpin(&mut noop_cx) else {
            panic!("Expected create to be ready");
        };
        assert!(result.is_err());
        assert_matches!(
            result.err().unwrap(),
            Error::Packet(bt_common::packet_encoding::Error::UnexpectedDataLength)
        );
    }

    #[test]
    fn create_fails_rank_invalid_length() {
        let mut service = FakePeerService::new();
        let mut noop_cx = Context::from_waker(noop_waker_ref());

        let mut sirk_val = vec![0x01];
        sirk_val.extend_from_slice(&[0xAB; 16]);
        add_char(&mut service, SIRK_HANDLE, SET_IDENTITY_RESOLVING_KEY_UUID, sirk_val);
        add_char(&mut service, RANK_HANDLE, SET_MEMBER_RANK_UUID, vec![]); // Empty (0 bytes)

        let create_fut = CoordinatedSetIdentificationServiceClient::<FakeTypes>::create(service);
        pin_mut!(create_fut);
        let Poll::Ready(result) = create_fut.poll_unpin(&mut noop_cx) else {
            panic!("Expected create to be ready");
        };
        assert!(result.is_err());
        assert_matches!(
            result.err().unwrap(),
            Error::Packet(bt_common::packet_encoding::Error::UnexpectedDataLength)
        );
    }
}
