// 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 thiserror::Error;

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

use crate::types::*;

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

/// 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> {
    #[allow(dead_code)]
    gatt_client: T::PeerService,
    #[allow(dead_code)]
    sirk_handle: Handle,
    #[allow(dead_code)]
    size_handle: Option<Handle>,
    #[allow(dead_code)]
    lock_handle: Option<Handle>,
    #[allow(dead_code)]
    rank_handle: Option<Handle>,

    // Initial read values
    sirk: SetIdentityResolvingKey,
    size: Option<CoordinatedSetSize>,
    rank: Option<SetMemberRank>,
}

impl<T: bt_gatt::GattTypes> CoordinatedSetIdentificationServiceClient<T> {
    /// Discovers CSIS characteristics and reads initial characteristic values.
    /// See CSIS v1.1 Section 5, Table 5.1 and CSIP v1.1 Section 4.3.
    pub async fn create(gatt_client: T::PeerService) -> Result<Self, Error> {
        let discovered = gatt_client.discover_characteristics(None).await?;

        let mut sirk_chars = Vec::new();
        let mut size_chars = Vec::new();
        let mut rank_chars = Vec::new();
        let mut lock_chars = Vec::new();

        for ch in discovered {
            let service_char = ServiceCharacteristic::new(&gatt_client, ch);
            match service_char.uuid() {
                SET_IDENTITY_RESOLVING_KEY_UUID => sirk_chars.push(service_char),
                COORDINATED_SET_SIZE_UUID => size_chars.push(service_char),
                SET_MEMBER_RANK_UUID => rank_chars.push(service_char),
                SET_MEMBER_LOCK_UUID => lock_chars.push(service_char),
                _ => {}
            }
        }

        let (sirk_handle, sirk) = Self::read_sirk(&sirk_chars).await?;
        let (size_handle, size) = Self::read_size(&size_chars).await?;
        let (rank_handle, rank) = Self::read_rank(&rank_chars).await?;
        let lock_handle = Self::get_lock_handle(&lock_chars)?;

        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,
            sirk,
            size,
            rank,
        })
    }

    async fn read_sirk(
        chars: &[ServiceCharacteristic<'_, T>],
    ) -> Result<(Handle, SetIdentityResolvingKey), Error> {
        if chars.is_empty() {
            return Err(Error::MissingCharacteristic(SET_IDENTITY_RESOLVING_KEY_UUID));
        }
        if chars.len() > 1 {
            return Err(Error::ExtraCharacteristic(SET_IDENTITY_RESOLVING_KEY_UUID));
        }
        let char_item = &chars[0];
        let handle = *char_item.handle();

        let mut buf = [0; SetIdentityResolvingKey::BYTE_SIZE];
        let bytes_read = char_item.read(&mut buf).await?;
        let (sirk_res, _) = SetIdentityResolvingKey::decode(&buf[..bytes_read]);
        let sirk = sirk_res?;

        Ok((handle, sirk))
    }

    async fn read_size(
        chars: &[ServiceCharacteristic<'_, T>],
    ) -> Result<(Option<Handle>, Option<CoordinatedSetSize>), Error> {
        if chars.is_empty() {
            return Ok((None, None));
        }
        if chars.len() > 1 {
            return Err(Error::ExtraCharacteristic(COORDINATED_SET_SIZE_UUID));
        }
        let char_item = &chars[0];
        let handle = *char_item.handle();

        let mut buf = [0; CoordinatedSetSize::BYTE_SIZE];
        let bytes_read = char_item.read(&mut buf).await?;
        let (size_res, _) = CoordinatedSetSize::decode(&buf[..bytes_read]);
        let size = size_res?;

        Ok((Some(handle), Some(size)))
    }

    async fn read_rank(
        chars: &[ServiceCharacteristic<'_, T>],
    ) -> Result<(Option<Handle>, Option<SetMemberRank>), Error> {
        if chars.is_empty() {
            return Ok((None, None));
        }
        if chars.len() > 1 {
            return Err(Error::ExtraCharacteristic(SET_MEMBER_RANK_UUID));
        }
        let char_item = &chars[0];
        let handle = *char_item.handle();

        let mut buf = [0; SetMemberRank::BYTE_SIZE];
        let bytes_read = char_item.read(&mut buf).await?;
        let (rank_res, _) = SetMemberRank::decode(&buf[..bytes_read]);
        let rank = rank_res?;

        Ok((Some(handle), Some(rank)))
    }

    fn get_lock_handle(chars: &[ServiceCharacteristic<'_, T>]) -> Result<Option<Handle>, Error> {
        if chars.is_empty() {
            return Ok(None);
        }
        if chars.len() > 1 {
            return Err(Error::ExtraCharacteristic(SET_MEMBER_LOCK_UUID));
        }
        Ok(Some(*chars[0].handle()))
    }

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

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

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

    // TODO(b/534436497): Add lock() and unlock() methods for Exclusive
    // Access & Set Member Locking. TODO(b/534436497): Add notification stream
    // support for Lock and Size characteristics.
}

#[cfg(test)]
mod tests {
    use super::*;
    use assert_matches::assert_matches;
    use bt_gatt::test_utils::*;
    use bt_gatt::types::{
        AttributePermissions, CharacteristicProperties, 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: CharacteristicProperties(vec![CharacteristicProperty::Read]),
                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_char(&mut service, LOCK_HANDLE, SET_MEMBER_LOCK_UUID, 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())));
    }

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

    #[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_char(&mut service, LOCK_HANDLE, SET_MEMBER_LOCK_UUID, 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_char(&mut service, LOCK_HANDLE, SET_MEMBER_LOCK_UUID, vec![0x01]);
        add_char(&mut service, Handle(5), SET_MEMBER_LOCK_UUID, 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_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)
        );
    }
}
