/*
 * Copyright (C) 2023 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.healthconnect.cts.lib;

import static androidx.test.InstrumentationRegistry.getContext;

import static com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity;

import static com.google.common.truth.Truth.assertThat;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.health.connect.HealthConnectException;
import android.health.connect.HealthConnectManager;
import android.health.connect.InsertRecordsResponse;
import android.health.connect.ReadRecordsRequest;
import android.health.connect.ReadRecordsResponse;
import android.health.connect.RecordIdFilter;
import android.health.connect.changelog.ChangeLogTokenRequest;
import android.health.connect.changelog.ChangeLogTokenResponse;
import android.health.connect.changelog.ChangeLogsRequest;
import android.health.connect.changelog.ChangeLogsResponse;
import android.health.connect.datatypes.BasalMetabolicRateRecord;
import android.health.connect.datatypes.DataOrigin;
import android.health.connect.datatypes.Device;
import android.health.connect.datatypes.ExerciseRoute;
import android.health.connect.datatypes.ExerciseSessionRecord;
import android.health.connect.datatypes.ExerciseSessionType;
import android.health.connect.datatypes.HeartRateRecord;
import android.health.connect.datatypes.Metadata;
import android.health.connect.datatypes.Record;
import android.health.connect.datatypes.StepsRecord;
import android.health.connect.datatypes.units.Power;
import android.os.Bundle;
import android.os.OutcomeReceiver;
import android.util.Log;

import androidx.test.core.app.ApplicationProvider;

import com.android.cts.install.lib.TestApp;

import java.io.Serializable;
import java.time.Instant;
import java.time.ZoneOffset;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicReference;

public class TestUtils {
    static final String TAG = "HealthConnectTest";
    public static final String READ_EXERCISE_ROUTE_PERMISSION =
            "android.permission.health.READ_EXERCISE_ROUTE";
    public static final String QUERY_TYPE = "android.healthconnect.cts.queryType";
    public static final String INTENT_EXTRA_CALLING_PKG = "android.healthconnect.cts.calling_pkg";
    public static final String APP_PKG_NAME_USED_IN_DATA_ORIGIN =
            "android.healthconnect.cts.pkg.usedInDataOrigin";
    public static final String INSERT_RECORD_QUERY = "android.healthconnect.cts.insertRecord";
    public static final String READ_RECORDS_QUERY = "android.healthconnect.cts.readRecords";
    public static final String READ_RECORDS_SIZE = "android.healthconnect.cts.readRecordsNumber";
    public static final String READ_USING_DATA_ORIGIN_FILTERS =
            "android.healthconnect.cts.readUsingDataOriginFilters";
    public static final String READ_RECORD_CLASS_NAME =
            "android.healthconnect.cts.readRecordsClass";
    public static final String READ_CHANGE_LOGS_QUERY = "android.healthconnect.cts.readChangeLogs";
    public static final String CHANGE_LOGS_RESPONSE =
            "android.healthconnect.cts.changeLogsResponse";
    public static final String CHANGE_LOG_TOKEN = "android.healthconnect.cts.changeLogToken";
    public static final String SUCCESS = "android.healthconnect.cts.success";
    public static final String CLIENT_ID = "android.healthconnect.cts.clientId";
    public static final String RECORD_IDS = "android.healthconnect.cts.records";
    public static final String DELETE_RECORDS_QUERY = "android.healthconnect.cts.deleteRecords";
    public static final String UPDATE_RECORDS_QUERY = "android.healthconnect.cts.updateRecords";
    public static final String UPDATE_EXERCISE_ROUTE = "android.healthconnect.cts.updateRoute";

    public static final String UPSERT_EXERCISE_ROUTE = "android.healthconnect.cts.upsertRoute";
    public static final String GET_CHANGE_LOG_TOKEN_QUERY =
            "android.healthconnect.cts.getChangeLogToken";
    public static final String INTENT_EXCEPTION = "android.healthconnect.cts.exception";
    private static final long POLLING_TIMEOUT_MILLIS = TimeUnit.SECONDS.toMillis(20);

    public static class RecordTypeAndRecordIds implements Serializable {
        private String mRecordType;
        private List<String> mRecordIds;

        public RecordTypeAndRecordIds(String recordType, List<String> ids) {
            mRecordType = recordType;
            mRecordIds = ids;
        }

        public String getRecordType() {
            return mRecordType;
        }

        public List<String> getRecordIds() {
            return mRecordIds;
        }
    }

    public static Bundle insertRecordAs(TestApp testApp) throws Exception {
        Bundle bundle = new Bundle();
        bundle.putString(QUERY_TYPE, INSERT_RECORD_QUERY);

        return getFromTestApp(testApp, bundle);
    }

    public static Bundle deleteRecordsAs(
            TestApp testApp, List<RecordTypeAndRecordIds> listOfRecordIdsAndClass)
            throws Exception {
        Bundle bundle = new Bundle();
        bundle.putString(QUERY_TYPE, DELETE_RECORDS_QUERY);
        bundle.putSerializable(RECORD_IDS, (Serializable) listOfRecordIdsAndClass);

        return getFromTestApp(testApp, bundle);
    }

    public static Bundle updateRecordsAs(
            TestApp testAppToUpdateData, List<RecordTypeAndRecordIds> listOfRecordIdsAndClass)
            throws Exception {
        Bundle bundle = new Bundle();
        bundle.putString(QUERY_TYPE, UPDATE_RECORDS_QUERY);
        bundle.putSerializable(RECORD_IDS, (Serializable) listOfRecordIdsAndClass);

        return getFromTestApp(testAppToUpdateData, bundle);
    }

    public static Bundle updateRouteAs(TestApp testAppToUpdateData) throws Exception {
        Bundle bundle = new Bundle();
        bundle.putString(QUERY_TYPE, UPDATE_EXERCISE_ROUTE);
        return getFromTestApp(testAppToUpdateData, bundle);
    }

    public static Bundle insertSessionNoRouteAs(TestApp testAppToUpdateData) throws Exception {
        Bundle bundle = new Bundle();
        bundle.putString(QUERY_TYPE, UPSERT_EXERCISE_ROUTE);
        return getFromTestApp(testAppToUpdateData, bundle);
    }

    public static Bundle insertRecordWithAnotherAppPackageName(
            TestApp testAppToInsertData, TestApp testAppPkgNameUsed) throws Exception {
        Bundle bundle = new Bundle();
        bundle.putString(QUERY_TYPE, INSERT_RECORD_QUERY);
        bundle.putString(APP_PKG_NAME_USED_IN_DATA_ORIGIN, testAppPkgNameUsed.getPackageName());

        return getFromTestApp(testAppToInsertData, bundle);
    }

    public static Bundle readRecordsAs(TestApp testApp, ArrayList<String> recordClassesToRead)
            throws Exception {
        Bundle bundle = new Bundle();
        bundle.putString(QUERY_TYPE, READ_RECORDS_QUERY);
        bundle.putStringArrayList(READ_RECORD_CLASS_NAME, recordClassesToRead);

        return getFromTestApp(testApp, bundle);
    }

    public static Bundle insertRecordWithGivenClientId(TestApp testApp, double clientId)
            throws Exception {
        Bundle bundle = new Bundle();
        bundle.putString(QUERY_TYPE, INSERT_RECORD_QUERY);
        bundle.putDouble(CLIENT_ID, clientId);

        return getFromTestApp(testApp, bundle);
    }

    public static Bundle readRecordsUsingDataOriginFiltersAs(
            TestApp testApp, ArrayList<String> recordClassesToRead) throws Exception {
        Bundle bundle = new Bundle();
        bundle.putString(QUERY_TYPE, READ_RECORDS_QUERY);
        bundle.putStringArrayList(READ_RECORD_CLASS_NAME, recordClassesToRead);
        bundle.putBoolean(READ_USING_DATA_ORIGIN_FILTERS, true);

        return getFromTestApp(testApp, bundle);
    }

    public static Bundle readChangeLogsUsingDataOriginFiltersAs(
            TestApp testApp, String changeLogToken) throws Exception {
        Bundle bundle = new Bundle();
        bundle.putString(QUERY_TYPE, READ_CHANGE_LOGS_QUERY);
        bundle.putString(CHANGE_LOG_TOKEN, changeLogToken);
        bundle.putBoolean(READ_USING_DATA_ORIGIN_FILTERS, true);

        return getFromTestApp(testApp, bundle);
    }

    public static Bundle getChangeLogTokenAs(TestApp testApp, String pkgName) throws Exception {
        Bundle bundle = new Bundle();
        bundle.putString(QUERY_TYPE, GET_CHANGE_LOG_TOKEN_QUERY);
        bundle.putString(APP_PKG_NAME_USED_IN_DATA_ORIGIN, pkgName);

        return getFromTestApp(testApp, bundle);
    }

    private static Bundle getFromTestApp(TestApp testApp, Bundle bundleToCreateIntent)
            throws Exception {
        final CountDownLatch latch = new CountDownLatch(1);
        AtomicReference<Bundle> response = new AtomicReference<>();
        AtomicReference<Exception> exceptionAtomicReference = new AtomicReference<>();
        BroadcastReceiver broadcastReceiver =
                new BroadcastReceiver() {
                    @Override
                    public void onReceive(Context context, Intent intent) {
                        if (intent.hasExtra(INTENT_EXCEPTION)) {
                            exceptionAtomicReference.set(
                                    (Exception) (intent.getSerializableExtra(INTENT_EXCEPTION)));
                        } else {
                            response.set(intent.getExtras());
                        }
                        latch.countDown();
                    }
                };

        launchTestApp(testApp, bundleToCreateIntent, broadcastReceiver, latch);
        if (exceptionAtomicReference.get() != null) {
            throw exceptionAtomicReference.get();
        }
        return response.get();
    }

    private static void launchTestApp(
            TestApp testApp,
            Bundle bundleToCreateIntent,
            BroadcastReceiver broadcastReceiver,
            CountDownLatch latch)
            throws Exception {

        // Register broadcast receiver
        final IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction(bundleToCreateIntent.getString(QUERY_TYPE));
        intentFilter.addCategory(Intent.CATEGORY_DEFAULT);
        getContext().registerReceiver(broadcastReceiver, intentFilter, Context.RECEIVER_EXPORTED);

        // Launch the test app.
        final Intent intent = new Intent(Intent.ACTION_MAIN);
        intent.setPackage(testApp.getPackageName());
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
        intent.putExtra(INTENT_EXTRA_CALLING_PKG, getContext().getPackageName());
        intent.putExtras(bundleToCreateIntent);
        intent.addCategory(Intent.CATEGORY_LAUNCHER);
        intent.putExtras(bundleToCreateIntent);

        Thread.sleep(500);
        getContext().startActivity(intent);
        if (!latch.await(POLLING_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS)) {
            final String errorMessage =
                    "Timed out while waiting to receive "
                            + bundleToCreateIntent.getString(QUERY_TYPE)
                            + " intent from "
                            + testApp.getPackageName();
            throw new TimeoutException(errorMessage);
        }
        getContext().unregisterReceiver(broadcastReceiver);
    }

    public static String insertRecordAndGetId(Record record, Context context)
            throws InterruptedException {
        return insertRecords(Collections.singletonList(record), context)
                .get(0)
                .getMetadata()
                .getId();
    }

    public static List<RecordTypeAndRecordIds> insertRecordsAndGetIds(
            List<Record> records, Context context) throws InterruptedException {
        List<Record> insertedRecords = insertRecords(records, context);

        Map<String, List<String>> recordTypeToRecordIdsMap = new HashMap<>();
        for (Record record : insertedRecords) {
            recordTypeToRecordIdsMap.putIfAbsent(record.getClass().getName(), new ArrayList<>());
            recordTypeToRecordIdsMap
                    .get(record.getClass().getName())
                    .add(record.getMetadata().getId());
        }

        List<RecordTypeAndRecordIds> recordTypeAndRecordIdsList = new ArrayList<>();
        for (String recordType : recordTypeToRecordIdsMap.keySet()) {
            recordTypeAndRecordIdsList.add(
                    new RecordTypeAndRecordIds(
                            recordType, recordTypeToRecordIdsMap.get(recordType)));
        }

        return recordTypeAndRecordIdsList;
    }

    public static List<Record> insertRecords(List<Record> records, Context context)
            throws InterruptedException {
        CountDownLatch latch = new CountDownLatch(1);
        HealthConnectManager service = context.getSystemService(HealthConnectManager.class);
        assertThat(service).isNotNull();
        AtomicReference<List<Record>> response = new AtomicReference<>();
        AtomicReference<HealthConnectException> exceptionAtomicReference = new AtomicReference<>();
        service.insertRecords(
                records,
                Executors.newSingleThreadExecutor(),
                new OutcomeReceiver<>() {
                    @Override
                    public void onResult(InsertRecordsResponse result) {
                        response.set(result.getRecords());
                        latch.countDown();
                    }

                    @Override
                    public void onError(HealthConnectException exception) {
                        Log.e(TAG, exception.getMessage());
                        exceptionAtomicReference.set(exception);
                        latch.countDown();
                    }
                });
        assertThat(latch.await(3, TimeUnit.SECONDS)).isTrue();
        if (exceptionAtomicReference.get() != null) {
            throw exceptionAtomicReference.get();
        }
        assertThat(response.get()).hasSize(records.size());

        return response.get();
    }

    public static List<Record> getTestRecords(String packageName) {
        double clientId = Math.random();
        return getTestRecords(packageName, clientId);
    }

    public static List<Record> getTestRecords(String packageName, Double clientId) {
        return Arrays.asList(
                getExerciseSessionRecord(packageName, clientId, /* withRoute= */ true),
                getStepsRecord(packageName, clientId),
                getHeartRateRecord(packageName, clientId),
                getBasalMetabolicRateRecord(packageName, clientId));
    }

    public static ExerciseSessionRecord getExerciseSessionRecord(
            String packageName, double clientId, boolean withRoute) {
        Instant startTime = Instant.now().minusSeconds(3000).truncatedTo(ChronoUnit.MILLIS);
        Instant endTime = Instant.now();
        ExerciseSessionRecord.Builder builder =
                new ExerciseSessionRecord.Builder(
                                buildSessionMetadata(packageName, clientId),
                                startTime,
                                endTime,
                                ExerciseSessionType.EXERCISE_SESSION_TYPE_OTHER_WORKOUT)
                        .setEndZoneOffset(ZoneOffset.MAX)
                        .setStartZoneOffset(ZoneOffset.MIN)
                        .setNotes("notes")
                        .setTitle("title");

        if (withRoute) {
            builder.setRoute(
                    new ExerciseRoute(
                            List.of(
                                    new ExerciseRoute.Location.Builder(startTime, 50., 50.).build(),
                                    new ExerciseRoute.Location.Builder(
                                                    startTime.plusSeconds(2), 51., 51.)
                                            .build())));
        }
        return builder.build();
    }

    public static StepsRecord getStepsRecord(String packageName, double clientId) {
        Device device =
                new Device.Builder().setManufacturer("google").setModel("Pixel").setType(1).build();
        DataOrigin dataOrigin = new DataOrigin.Builder().setPackageName(packageName).build();
        return new StepsRecord.Builder(
                        new Metadata.Builder()
                                .setDevice(device)
                                .setDataOrigin(dataOrigin)
                                .setClientRecordId("SR" + clientId)
                                .build(),
                        Instant.now(),
                        Instant.now().plusMillis(1000),
                        10)
                .build();
    }

    public static HeartRateRecord getHeartRateRecord(String packageName, double clientId) {
        HeartRateRecord.HeartRateSample heartRateSample =
                new HeartRateRecord.HeartRateSample(72, Instant.now().plusMillis(100));
        ArrayList<HeartRateRecord.HeartRateSample> heartRateSamples = new ArrayList<>();
        heartRateSamples.add(heartRateSample);
        heartRateSamples.add(heartRateSample);
        Device device =
                new Device.Builder().setManufacturer("google").setModel("Pixel").setType(1).build();
        DataOrigin dataOrigin = new DataOrigin.Builder().setPackageName(packageName).build();

        return new HeartRateRecord.Builder(
                        new Metadata.Builder()
                                .setDevice(device)
                                .setDataOrigin(dataOrigin)
                                .setClientRecordId("HR" + clientId)
                                .build(),
                        Instant.now(),
                        Instant.now().plusMillis(500),
                        heartRateSamples)
                .build();
    }

    public static BasalMetabolicRateRecord getBasalMetabolicRateRecord(
            String packageName, double clientId) {
        Device device =
                new Device.Builder()
                        .setManufacturer("google")
                        .setModel("Pixel4a")
                        .setType(2)
                        .build();
        DataOrigin dataOrigin = new DataOrigin.Builder().setPackageName(packageName).build();
        return new BasalMetabolicRateRecord.Builder(
                        new Metadata.Builder()
                                .setDevice(device)
                                .setDataOrigin(dataOrigin)
                                .setClientRecordId("BMR" + clientId)
                                .build(),
                        Instant.now(),
                        Power.fromWatts(100.0))
                .build();
    }

    public static void verifyDeleteRecords(List<RecordIdFilter> request, Context context)
            throws InterruptedException {
        HealthConnectManager service = context.getSystemService(HealthConnectManager.class);
        CountDownLatch latch = new CountDownLatch(1);
        AtomicReference<HealthConnectException> exceptionAtomicReference = new AtomicReference<>();
        assertThat(service).isNotNull();
        service.deleteRecords(
                request,
                Executors.newSingleThreadExecutor(),
                new OutcomeReceiver<>() {
                    @Override
                    public void onResult(Void result) {
                        latch.countDown();
                    }

                    @Override
                    public void onError(HealthConnectException healthConnectException) {
                        exceptionAtomicReference.set(healthConnectException);
                        latch.countDown();
                    }
                });
        assertThat(latch.await(3, TimeUnit.SECONDS)).isEqualTo(true);
        if (exceptionAtomicReference.get() != null) {
            throw exceptionAtomicReference.get();
        }
    }

    public static <T extends Record> List<T> readRecords(
            ReadRecordsRequest<T> request, Context context) throws InterruptedException {
        HealthConnectManager service = context.getSystemService(HealthConnectManager.class);
        CountDownLatch latch = new CountDownLatch(1);
        assertThat(service).isNotNull();
        assertThat(request.getRecordType()).isNotNull();
        AtomicReference<List<T>> response = new AtomicReference<>();
        AtomicReference<HealthConnectException> healthConnectExceptionAtomicReference =
                new AtomicReference<>();
        service.readRecords(
                request,
                Executors.newSingleThreadExecutor(),
                new OutcomeReceiver<>() {
                    @Override
                    public void onResult(ReadRecordsResponse<T> result) {
                        response.set(result.getRecords());
                        latch.countDown();
                    }

                    @Override
                    public void onError(HealthConnectException exception) {
                        Log.e(TAG, exception.getMessage());
                        healthConnectExceptionAtomicReference.set(exception);
                        latch.countDown();
                    }
                });
        assertThat(latch.await(3, TimeUnit.SECONDS)).isEqualTo(true);
        if (healthConnectExceptionAtomicReference.get() != null) {
            throw healthConnectExceptionAtomicReference.get();
        }
        return response.get();
    }

    public static void updateRecords(List<Record> records, Context context)
            throws InterruptedException {
        CountDownLatch latch = new CountDownLatch(1);
        HealthConnectManager service = context.getSystemService(HealthConnectManager.class);
        assertThat(service).isNotNull();
        AtomicReference<HealthConnectException> exceptionAtomicReference = new AtomicReference<>();

        service.updateRecords(
                records,
                Executors.newSingleThreadExecutor(),
                new OutcomeReceiver<>() {
                    @Override
                    public void onResult(Void result) {
                        latch.countDown();
                    }

                    @Override
                    public void onError(HealthConnectException exception) {
                        exceptionAtomicReference.set(exception);
                        latch.countDown();
                    }
                });
        assertThat(latch.await(3, TimeUnit.SECONDS)).isTrue();
        if (exceptionAtomicReference.get() != null) {
            throw exceptionAtomicReference.get();
        }
    }

    public static <T extends Record> List<T> readRecords(ReadRecordsRequest<T> request)
            throws InterruptedException {
        Context context = ApplicationProvider.getApplicationContext();
        HealthConnectManager service = context.getSystemService(HealthConnectManager.class);
        CountDownLatch latch = new CountDownLatch(1);
        assertThat(service).isNotNull();
        assertThat(request.getRecordType()).isNotNull();
        AtomicReference<List<T>> response = new AtomicReference<>();
        AtomicReference<HealthConnectException> healthConnectExceptionAtomicReference =
                new AtomicReference<>();
        service.readRecords(
                request,
                Executors.newSingleThreadExecutor(),
                new OutcomeReceiver<>() {
                    @Override
                    public void onResult(ReadRecordsResponse<T> result) {
                        response.set(result.getRecords());
                        latch.countDown();
                    }

                    @Override
                    public void onError(HealthConnectException exception) {
                        Log.e(TAG, exception.getMessage());
                        healthConnectExceptionAtomicReference.set(exception);
                        latch.countDown();
                    }
                });
        assertThat(latch.await(3, TimeUnit.SECONDS)).isEqualTo(true);
        if (healthConnectExceptionAtomicReference.get() != null) {
            throw healthConnectExceptionAtomicReference.get();
        }
        return response.get();
    }

    public static ChangeLogTokenResponse getChangeLogToken(
            ChangeLogTokenRequest request, Context context) throws InterruptedException {
        HealthConnectManager service = context.getSystemService(HealthConnectManager.class);
        assertThat(service).isNotNull();
        CountDownLatch latch = new CountDownLatch(1);
        AtomicReference<ChangeLogTokenResponse> response = new AtomicReference<>();
        AtomicReference<HealthConnectException> exceptionAtomicReference = new AtomicReference<>();
        service.getChangeLogToken(
                request,
                Executors.newSingleThreadExecutor(),
                new OutcomeReceiver<>() {
                    @Override
                    public void onResult(ChangeLogTokenResponse result) {
                        response.set(result);
                        latch.countDown();
                    }

                    @Override
                    public void onError(HealthConnectException exception) {
                        Log.e(TAG, exception.getMessage());
                        exceptionAtomicReference.set(exception);
                        latch.countDown();
                    }
                });
        assertThat(latch.await(3, TimeUnit.SECONDS)).isTrue();
        if (exceptionAtomicReference.get() != null) {
            throw exceptionAtomicReference.get();
        }
        return response.get();
    }

    public static ChangeLogsResponse getChangeLogs(
            ChangeLogsRequest changeLogsRequest, Context context) throws InterruptedException {
        HealthConnectManager service = context.getSystemService(HealthConnectManager.class);
        assertThat(service).isNotNull();

        CountDownLatch latch = new CountDownLatch(1);
        AtomicReference<ChangeLogsResponse> response = new AtomicReference<>();
        AtomicReference<HealthConnectException> healthConnectExceptionAtomicReference =
                new AtomicReference<>();
        service.getChangeLogs(
                changeLogsRequest,
                Executors.newSingleThreadExecutor(),
                new OutcomeReceiver<>() {
                    @Override
                    public void onResult(ChangeLogsResponse result) {
                        response.set(result);
                        latch.countDown();
                    }

                    @Override
                    public void onError(HealthConnectException exception) {
                        healthConnectExceptionAtomicReference.set(exception);
                        latch.countDown();
                    }
                });
        assertThat(latch.await(3, TimeUnit.SECONDS)).isEqualTo(true);
        if (healthConnectExceptionAtomicReference.get() != null) {
            throw healthConnectExceptionAtomicReference.get();
        }

        return response.get();
    }

    public static void deleteAllStagedRemoteData() {
        Context context = ApplicationProvider.getApplicationContext();
        HealthConnectManager service = context.getSystemService(HealthConnectManager.class);
        assertThat(service).isNotNull();
        runWithShellPermissionIdentity(
                () ->
                        // TODO(b/241542162): Avoid reflection once TestApi can be called from CTS
                        service.getClass().getMethod("deleteAllStagedRemoteData").invoke(service),
                "android.permission.DELETE_STAGED_HEALTH_CONNECT_REMOTE_DATA");
    }

    private static Metadata buildSessionMetadata(String packageName, double clientId) {
        Device device =
                new Device.Builder().setManufacturer("google").setModel("Pixel").setType(1).build();
        DataOrigin dataOrigin = new DataOrigin.Builder().setPackageName(packageName).build();
        return new Metadata.Builder()
                .setDevice(device)
                .setDataOrigin(dataOrigin)
                .setClientRecordId(String.valueOf(clientId))
                .build();
    }
}
