@Override
  public ImportResult importItem(
      UUID jobId,
      IdempotentImportExecutor idempotentExecutor,
      TokensAndUrlAuthData authData,
      MediaContainerResource data)
      throws Exception {
    if (data == null) {
      return ImportResult.OK;
    }

    for (PhotoModel photoModel: data.getPhotos()) {
      monitor.debug(() -> "AppleMediaImporter received data",
              AuditKeys.dataId, photoModel.getDataId(),
              AuditKeys.updatedTimeInMs, photoModel.getUploadedTime());
    }

    AppleMediaInterface mediaInterface = factory
      .getOrCreateMediaInterface(jobId, authData, appCredentials, exportingService, monitor);

    final int albumCount =
        mediaInterface.importAlbums(
            jobId,
            idempotentExecutor,
            data.getAlbums(),
          DataVertical.MEDIA.getDataType());
    final Map<String, Long> importPhotosMap =
        mediaInterface.importAllMedia(
            jobId,
            idempotentExecutor,
            data.getPhotos(),
          DataVertical.MEDIA.getDataType());
    final Map<String, Long> importVideosResult =
        mediaInterface.importAllMedia(
            jobId,
            idempotentExecutor,
            data.getVideos(),
          DataVertical.MEDIA.getDataType());

    final Map<String, Integer> counts =
        new ImmutableMap.Builder<String, Integer>()
            .put(MediaContainerResource.ALBUMS_COUNT_DATA_NAME, albumCount)
            .put(
                MediaContainerResource.PHOTOS_COUNT_DATA_NAME,
                importPhotosMap.getOrDefault(ApplePhotosConstants.COUNT_KEY, 0L).intValue())
            .put(
                MediaContainerResource.VIDEOS_COUNT_DATA_NAME,
                importVideosResult.getOrDefault(ApplePhotosConstants.COUNT_KEY, 0L).intValue())
            .build();

    monitor.info(() -> "AppleMediaImporter imported batch",
            MediaContainerResource.ALBUMS_COUNT_DATA_NAME, albumCount,
            MediaContainerResource.PHOTOS_COUNT_DATA_NAME, importPhotosMap.getOrDefault(ApplePhotosConstants.COUNT_KEY, 0L).intValue(),
            MediaContainerResource.VIDEOS_COUNT_DATA_NAME, importVideosResult.getOrDefault(ApplePhotosConstants.COUNT_KEY, 0L).intValue());

    return ImportResult.OK
        .copyWithBytes(
            importPhotosMap.getOrDefault(ApplePhotosConstants.BYTES_KEY, 0L)
                + importVideosResult.getOrDefault(ApplePhotosConstants.BYTES_KEY, 0L))
        .copyWithCounts(counts);
  }
@Test
  public void importPhotosVideosAndAlbums() throws Exception {
    // set up albums
    final int albumCount = 1;
    final List<MediaAlbum> mediaAlbums =
        createTestAlbums(albumCount).stream()
            .map(MediaAlbum::photoToMediaAlbum)
            .collect(Collectors.toList());
    setUpCreateAlbumsResponse(
        mediaAlbums.stream()
            .collect(
                Collectors.toMap(MediaAlbum::getId, photoAlbum -> SC_OK)));

    // set up photos
    final int photoCount = 2;
    final List<PhotoModel> photos = createTestPhotos(photoCount);
    final Map<String, Integer> dataIdToStatus =
        photos.stream()
            .collect(
                Collectors.toMap(PhotoModel::getDataId, photoModel -> SC_OK));

    // set up videos
    final int videoCount = 3;
    final List<VideoModel> videos =
        createTestVideos(videoCount).stream().collect(Collectors.toList());
    dataIdToStatus.putAll(
        videos.stream()
            .collect(
                Collectors.toMap(
                    VideoModel::getDataId, videoModel -> SC_OK)));
    setUpGetUploadUrlResponse(dataIdToStatus);
    setUpUploadContentResponse(dataIdToStatus);
    setUpCreateMediaResponse(dataIdToStatus);

    MediaContainerResource mediaData = new MediaContainerResource(mediaAlbums, photos, videos);

    final ImportResult importResult =
        appleMediaImporter.importItem(uuid, executor, authData, mediaData);

    // verify correct methods were called
    final List<String> photosDataIds =
        photos.stream().map(PhotoModel::getDataId).collect(Collectors.toList());
    final List<String> videosDataIds =
        videos.stream().map(VideoModel::getDataId).collect(Collectors.toList());

    verify(mediaInterface)
        .createAlbums(uuid.toString(), DataVertical.MEDIA.getDataType(), mediaAlbums);
    verify(mediaInterface)
        .getUploadUrl(uuid.toString(), DataVertical.MEDIA.getDataType(), photosDataIds);
    verify(mediaInterface)
        .getUploadUrl(uuid.toString(), DataVertical.MEDIA.getDataType(), videosDataIds);
    verify(mediaInterface, times(2)).uploadContent(anyMap(), anyList());
    verify(mediaInterface, times(2)).createMedia(anyString(), anyString(), argThat(newMediaRequestList -> {
      assertThat(newMediaRequestList).isNotNull();
      assertThat(newMediaRequestList.stream().allMatch(newMediaRequest -> newMediaRequest.hasCreationDateInMillis())).isTrue();
      assertThat(newMediaRequestList.stream().allMatch(newMediaRequest -> newMediaRequest.hasIsFavorite() && newMediaRequest.getIsFavorite()==1L)).isTrue();
      return true;
    }));

    // check the result
    assertThat(importResult.getCounts().isPresent()).isTrue();
    assertThat(
        importResult.getCounts().get().get(PhotosContainerResource.ALBUMS_COUNT_DATA_NAME) == 1).isTrue();
    assertThat(
        importResult.getCounts().get().get(PhotosContainerResource.PHOTOS_COUNT_DATA_NAME)
            == photoCount).isTrue();
    assertThat(
        importResult.getCounts().get().get(VideosContainerResource.VIDEOS_COUNT_DATA_NAME)
            == videoCount).isTrue();

    assertThat(
        importResult.getBytes().get()
            == photoCount * PHOTOS_FILE_SIZE + videoCount * VIDEOS_FILE_SIZE).isTrue();

    final Map<String, Serializable> expectedKnownValue =
        mediaAlbums.stream()
            .collect(
                Collectors.toMap(
                    MediaAlbum::getId, mediaAlbum -> ALBUM_RECORDID_BASE + mediaAlbum.getId()));
    expectedKnownValue.putAll(
        photos.stream()
            .collect(
                Collectors.toMap(
                    photoModel -> photoModel.getAlbumId() + "-" + photoModel.getDataId(),
                    photoModel -> MEDIA_RECORDID_BASE + photoModel.getDataId())));
    expectedKnownValue.putAll(
        videos.stream()
            .collect(
                Collectors.toMap(
                    videoModel -> videoModel.getAlbumId() + "-" +videoModel.getDataId(),
                    videoModel -> MEDIA_RECORDID_BASE + videoModel.getDataId())));
    checkKnownValues(expectedKnownValue);
  }