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

#![allow(dead_code)]

use bt_ascs::client::{ASE_CONTROL_POINT_UUID, SINK_ASE_UUID, SOURCE_ASE_UUID};
use bt_ascs::server::ASCS_UUID;
use bt_ascs::types::{
    AseAdditionalParameters, AseId, AseState, AudioDirection, AudioStreamEndpoint,
};
use bt_common::core::{CodecId, CodingFormat};
use bt_common::packet_encoding::Encodable;
use bt_gatt::client::FromCharacteristic;
use bt_gatt::test_utils::{FakeClient, FakePeerService};
use bt_gatt::types::{
    AttributePermissions, Characteristic, CharacteristicProperties, CharacteristicProperty, Handle,
};
use bt_pacs::{PacRecord, SourcePac, PACS_UUID};

pub const SOURCE_PAC_HANDLE: Handle = Handle(1);
pub const SINK_ASE_HANDLE: Handle = Handle(2);
pub const CONTROL_POINT_HANDLE: Handle = Handle(3);
pub const SOURCE_ASE_HANDLE: Handle = Handle(4);

pub const DEFAULT_SINK_ASE_ID: AseId = AseId(1);
pub const DEFAULT_SOURCE_ASE_ID: AseId = AseId(2);

/// Creates a `FakePeerService` configured as a PACS service with a single
/// Source PAC record for LC3.
pub fn create_pacs_service() -> FakePeerService {
    let mut pacs_service = FakePeerService::new();
    let pac_record = PacRecord {
        codec_id: CodecId::Assigned(CodingFormat::Lc3),
        codec_specific_capabilities: vec![],
        metadata: vec![],
    };

    let mut pac_buf = vec![0; 1 + pac_record.encoded_len()];
    pac_buf[0] = 1; // 1 record
    pac_record.encode(&mut pac_buf[1..]).unwrap();

    let source_pac_chr = Characteristic {
        handle: SOURCE_PAC_HANDLE,
        uuid: SourcePac::UUID,
        properties: CharacteristicProperty::Read.into(),
        permissions: AttributePermissions::default(),
        descriptors: vec![],
    };
    pacs_service.add_characteristic(source_pac_chr, pac_buf);
    pacs_service
}

/// Sets up a PACS service in `client` with a single Source PAC record for LC3.
/// Adds the service to `client` and returns the `FakePeerService`.
pub fn setup_pacs_service(client: &mut FakeClient) -> FakePeerService {
    let pacs_service = create_pacs_service();
    client.add_service(PACS_UUID, true, pacs_service.clone());
    pacs_service
}

/// Creates a `FakePeerService` configured as an ASCS service with
/// `sink_ase_count` sink ASEs, `source_ase_count` source ASEs, and a Control
/// Point initialized with `control_point_val`.
pub fn create_ascs_service(
    sink_ase_count: usize,
    source_ase_count: usize,
    control_point_val: Vec<u8>,
) -> FakePeerService {
    let mut ascs_service = FakePeerService::new();

    let control_point_chr = Characteristic {
        handle: CONTROL_POINT_HANDLE,
        uuid: ASE_CONTROL_POINT_UUID,
        properties: CharacteristicProperties::WRITE_NOTIFY,
        permissions: AttributePermissions::default(),
        descriptors: vec![],
    };
    ascs_service.add_characteristic(control_point_chr, control_point_val);

    // ASE ids and handles are allocated from iterators shared by every endpoint
    // characteristic, so sinks and sources can never collide with each other.
    // The handle reserved for the control point characteristic is skipped.
    let mut ase_ids = (1..).map(AseId);
    let mut handles = (SINK_ASE_HANDLE.0..).map(Handle).filter(|h| *h != CONTROL_POINT_HANDLE);

    let directions = std::iter::repeat_n(AudioDirection::Sink, sink_ase_count)
        .chain(std::iter::repeat_n(AudioDirection::Source, source_ase_count));

    for direction in directions {
        let endpoint = AudioStreamEndpoint {
            handle: Handle(0),
            direction,
            ase_id: ase_ids.next().expect("ase ids available"),
            state: AseState::Idle,
            additional: AseAdditionalParameters::None,
        };
        let mut ase_buf = vec![0; endpoint.encoded_len()];
        endpoint.encode(&mut ase_buf).unwrap();

        let uuid = match direction {
            AudioDirection::Sink => SINK_ASE_UUID,
            AudioDirection::Source => SOURCE_ASE_UUID,
        };
        let ase_chr = Characteristic {
            handle: handles.next().expect("handles available"),
            uuid,
            properties: CharacteristicProperties::READ_NOTIFY,
            permissions: AttributePermissions::default(),
            descriptors: vec![],
        };
        ascs_service.add_characteristic(ase_chr, ase_buf);
    }

    ascs_service
}

/// Sets up an ASCS service in `client` with `sink_ase_count` sink ASEs,
/// `source_ase_count` source ASEs, and an empty Control Point. Adds the service
/// to `client` and returns the `FakePeerService`.
pub fn setup_ascs_service(
    client: &mut FakeClient,
    sink_ase_count: usize,
    source_ase_count: usize,
) -> FakePeerService {
    setup_ascs_service_with_cp_value(client, sink_ase_count, source_ase_count, vec![])
}

/// Sets up an ASCS service in `client` with `sink_ase_count` sink ASEs,
/// `source_ase_count` source ASEs, and a Control Point initialized with
/// `control_point_val`. Adds the service to `client` and returns the
/// `FakePeerService`.
pub fn setup_ascs_service_with_cp_value(
    client: &mut FakeClient,
    sink_ase_count: usize,
    source_ase_count: usize,
    control_point_val: Vec<u8>,
) -> FakePeerService {
    let ascs_service = create_ascs_service(sink_ase_count, source_ase_count, control_point_val);
    client.add_service(ASCS_UUID, true, ascs_service.clone());
    ascs_service
}
