/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you 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 org.apache.directory.scim.server.rest;

import java.util.*;
import java.util.regex.Pattern;

import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
import jakarta.ws.rs.core.Response;
import jakarta.ws.rs.core.Response.Status;
import jakarta.ws.rs.core.UriInfo;

import org.apache.commons.lang3.StringUtils;
import org.apache.directory.scim.core.repository.ResourceException;
import org.apache.directory.scim.server.exception.UnableToCreateResourceException;
import org.apache.directory.scim.server.exception.UnableToDeleteResourceException;
import org.apache.directory.scim.server.exception.UnableToRetrieveResourceException;
import org.apache.directory.scim.server.exception.UnableToUpdateResourceException;
import org.apache.directory.scim.core.repository.Repository;
import org.apache.directory.scim.core.repository.RepositoryRegistry;
import org.apache.directory.scim.core.repository.UpdateRequest;
import org.apache.directory.scim.protocol.BulkResource;
import org.apache.directory.scim.protocol.data.BulkOperation;
import org.apache.directory.scim.protocol.data.BulkOperation.Method;
import org.apache.directory.scim.protocol.data.BulkOperation.StatusWrapper;
import org.apache.directory.scim.protocol.data.BulkRequest;
import org.apache.directory.scim.protocol.data.BulkResponse;
import org.apache.directory.scim.protocol.data.ErrorResponse;
import org.apache.directory.scim.spec.resources.BaseResource;
import org.apache.directory.scim.spec.resources.ScimResource;
import org.apache.directory.scim.spec.schema.Schema;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.directory.scim.core.schema.SchemaRegistry;

@Slf4j
@ApplicationScoped
public class BulkResourceImpl implements BulkResource {
//  private static final StatusWrapper OKAY_STATUS = new StatusWrapper();
//  private static final StatusWrapper CREATED_STATUS = new StatusWrapper();
//  private static final StatusWrapper NO_CONTENT_STATUS = new StatusWrapper();
//  private static final StatusWrapper METHOD_NOT_ALLOWED_STATUS = new StatusWrapper();
//  private static final StatusWrapper CONFLICT_STATUS = new StatusWrapper();
//  private static final StatusWrapper CLIENT_ERROR_STATUS = new StatusWrapper();
//  private static final StatusWrapper NOT_FOUND_STATUS = new StatusWrapper();
//  private static final StatusWrapper INTERNAL_SERVER_ERROR_STATUS = new StatusWrapper();
//  private static final StatusWrapper METHOD_NOT_IMPLEMENTED_STATUS = new StatusWrapper();
//  private static final String OKAY = "200";
//  private static final String CREATED = "201";
//  private static final String NO_CONTENT = "204";
//  private static final String CLIENT_ERROR = "400";
//  private static final String NOT_FOUND = "404";
//  private static final String METHOD_NOT_ALLOWED = "405";
//  private static final String CONFLICT = "409";
//  private static final String INTERNAL_SERVER_ERROR = "500";
//  private static final String METHOD_NOT_IMPLEMENTED = "501";
  private static final String BULK_ID_DOES_NOT_EXIST = "Bulk ID cannot be resolved because it refers to no bulkId in any Bulk Operation: %s";
  private static final String BULK_ID_REFERS_TO_FAILED_RESOURCE = "Bulk ID cannot be resolved because the resource it refers to had failed to be created: %s";
  private static final String OPERATION_DEPENDS_ON_FAILED_OPERATION = "Operation depends on failed bulk operation: %s";
  private static final Pattern PATH_PATTERN = Pattern.compile("^/[^/]+/[^/]+$");

//  static {
//    METHOD_NOT_ALLOWED_STATUS.setCode(METHOD_NOT_ALLOWED);
//    OKAY_STATUS.setCode(OKAY);
//    CREATED_STATUS.setCode(CREATED);
//    NO_CONTENT_STATUS.setCode(NO_CONTENT);
//    CONFLICT_STATUS.setCode(CONFLICT);
//    CLIENT_ERROR_STATUS.setCode(CLIENT_ERROR);
//    NOT_FOUND_STATUS.setCode(NOT_FOUND);
//    INTERNAL_SERVER_ERROR_STATUS.setCode(INTERNAL_SERVER_ERROR);
//    METHOD_NOT_IMPLEMENTED_STATUS.setCode(METHOD_NOT_IMPLEMENTED);
//  }

  private final SchemaRegistry schemaRegistry;

  private final RepositoryRegistry repositoryRegistry;

  @Inject
  public BulkResourceImpl(SchemaRegistry schemaRegistry, RepositoryRegistry repositoryRegistry) {
    this.schemaRegistry = schemaRegistry;
    this.repositoryRegistry = repositoryRegistry;
  }

  BulkResourceImpl() {
    this(null, null);
  }

  @Override
  public Response doBulk(BulkRequest request, UriInfo uriInfo) {
    BulkResponse response;
    int errorCount = 0;
    Integer requestFailOnErrors = request.getFailOnErrors();
    int maxErrorCount = requestFailOnErrors != null && requestFailOnErrors > 0 ? requestFailOnErrors : Integer.MAX_VALUE;
    int errorCountIncrement = requestFailOnErrors == null || requestFailOnErrors > 0 ? 1 : 0;
    List<BulkOperation> bulkOperations = request.getOperations();
    Map<String, BulkOperation> bulkIdKeyToOperationResult = new HashMap<>();
    List<IWishJavaHadTuples> allUnresolveds = new ArrayList<>();
    Map<String, Set<String>> reverseDependenciesGraph = this.generateReverseDependenciesGraph(bulkOperations);
    Map<String, Set<String>> transitiveReverseDependencies = generateTransitiveDependenciesGraph(reverseDependenciesGraph);

    log.debug("Reverse dependencies: {}", reverseDependenciesGraph);
    log.debug("Transitive reverse dependencies: {}", transitiveReverseDependencies);

    // clean out unwanted data
    for (BulkOperation operationRequest : bulkOperations) {
      operationRequest.setResponse(null);
      operationRequest.setStatus(null);
    }
    // get all known bulkIds, handle bad input
    for (BulkOperation operationRequest : bulkOperations) {
      String bulkId = operationRequest.getBulkId();
      Method method = operationRequest.getMethod();
      String bulkIdKey = bulkId != null ? "bulkId:" + bulkId : null;
      boolean errorOccurred = false;

      // duplicate bulkId
      if (bulkIdKey != null) {
        if (!bulkIdKeyToOperationResult.containsKey(bulkIdKey)) {
          bulkIdKeyToOperationResult.put(bulkIdKey, operationRequest);
        } else {
          errorOccurred = true;
          BulkOperation duplicateOperation = bulkIdKeyToOperationResult.get(bulkIdKey);

          createAndSetErrorResponse(operationRequest, Status.CONFLICT, "Duplicate bulkId");

          if (!(duplicateOperation.getResponse() instanceof ErrorResponse)) {
            duplicateOperation.setData(null);
            createAndSetErrorResponse(duplicateOperation, Status.CONFLICT, "Duplicate bulkId");
          }
        }
      }
      // bad/missing input for method
      if (method != null && !(operationRequest.getResponse() instanceof ErrorResponse)) {
        switch (method) {
        case POST:
        case PUT: {
          if (operationRequest.getData() == null) {
            errorOccurred = true;

            createAndSetErrorResponse(operationRequest, Status.BAD_REQUEST, "data not provided");
          }
        }
          break;

        case DELETE: {
          String path = operationRequest.getPath();

          if (path == null) {
            errorOccurred = true;

            createAndSetErrorResponse(operationRequest, Status.BAD_REQUEST, "path not provided");
          } else if (!PATH_PATTERN.matcher(path)
                                  .matches()) {
            errorOccurred = true;

            createAndSetErrorResponse(operationRequest, Status.BAD_REQUEST, "path is not a valid path (e.g. \"/Groups/123abc\", \"/Users/123xyz\", ...)");
          } else {
            String endPoint = path.substring(0, path.lastIndexOf('/'));
            Class<ScimResource> clazz = (Class<ScimResource>) schemaRegistry.findScimResourceClassFromEndpoint(endPoint);

            if (clazz == null) {
              errorOccurred = true;

              createAndSetErrorResponse(operationRequest, Status.BAD_REQUEST, "path does not contain a recognized endpoint (e.g. \"/Groups/...\", \"/Users/...\", ...)");
            }
          }
        }
          break;

        case PATCH: {
          errorOccurred = true;

          createAndSetErrorResponse(operationRequest, Status.NOT_IMPLEMENTED, "Method not implemented: PATCH");
        }
          break;

        default: {
        }
          break;
        }
      } else if (method == null) {
        errorOccurred = true;

        operationRequest.setData(null);
        createAndSetErrorResponse(operationRequest, Status.BAD_REQUEST, "no method provided (e.g. PUT, POST, ...");
      }
      if (errorOccurred) {
        operationRequest.setData(null);

        if (bulkIdKey != null) {
          Set<String> reverseDependencies = transitiveReverseDependencies.getOrDefault(bulkIdKey, Collections.emptySet());
          String detail = String.format(OPERATION_DEPENDS_ON_FAILED_OPERATION, bulkIdKey);

          for (String dependentBulkIdKey : reverseDependencies) {
            BulkOperation dependentOperation = bulkIdKeyToOperationResult.get(dependentBulkIdKey);

            if (!(dependentOperation.getResponse() instanceof ErrorResponse)) {
              dependentOperation.setData(null);
              createAndSetErrorResponse(dependentOperation, Status.CONFLICT, detail);
            }
          }
        }
      }
    }

    boolean errorCountExceeded = false;

    // do the operations
    for (BulkOperation operationResult : bulkOperations) {

      if (!errorCountExceeded && !(operationResult.getResponse() instanceof ErrorResponse)) {
        try {
          this.handleBulkOperationMethod(allUnresolveds, operationResult, bulkIdKeyToOperationResult, uriInfo);
        } catch (ResourceException resourceException) {
          log.error("Failed to do bulk operation", resourceException);

          errorCount += errorCountIncrement;
          errorCountExceeded = errorCount >= maxErrorCount;

          String detail = resourceException.getLocalizedMessage();
          createAndSetErrorResponse(operationResult, resourceException.getStatus(), detail);

          if (operationResult.getBulkId() != null) {
            String bulkIdKey = "bulkId:" + operationResult.getBulkId();

            this.cleanup(bulkIdKey, transitiveReverseDependencies, bulkIdKeyToOperationResult);
            operationResult.setData(null);
          }
        } catch (UnresolvableOperationException unresolvableOperationException) {
          log.error("Could not resolve bulkId during Bulk Operation method handling", unresolvableOperationException);

          errorCount += errorCountIncrement;
          String detail = unresolvableOperationException.getLocalizedMessage();

          createAndSetErrorResponse(operationResult, Status.CONFLICT, detail);

          if (operationResult.getBulkId() != null) {
            String bulkIdKey = "bulkId:" + operationResult.getBulkId();

            this.cleanup(bulkIdKey, transitiveReverseDependencies, bulkIdKeyToOperationResult);
            operationResult.setData(null);
          }
        }
      } else if (errorCountExceeded) {

        // continue processing bulk operations to cleanup any dependencies

        createAndSetErrorResponse(operationResult, Status.CONFLICT, "failOnErrors count reached");
        if (operationResult.getBulkId() != null) {
          String bulkIdKey = "bulkId:" + operationResult.getBulkId();

          this.cleanup(bulkIdKey, transitiveReverseDependencies, bulkIdKeyToOperationResult);
        }
      }
    }
    // Resolve unresolved bulkIds
    for (IWishJavaHadTuples iwjht : allUnresolveds) {
      BulkOperation bulkOperationResult = iwjht.bulkOperationResult;
      String bulkIdKey = iwjht.bulkIdKey;
      ScimResource scimResource = bulkOperationResult.getData();

      try {
        for (UnresolvedTopLevel unresolved : iwjht.unresolveds) {
          log.debug("Final resolution pass for {}", unresolved);
          unresolved.resolve(scimResource, bulkIdKeyToOperationResult);
        }
        String scimResourceId = scimResource.getId();
        @SuppressWarnings("unchecked")
        Class<ScimResource> scimResourceClass = (Class<ScimResource>) scimResource.getClass();
        Repository<ScimResource> repository = repositoryRegistry.getRepository(scimResourceClass);

        ScimResource original = repository.get(scimResourceId);

        UpdateRequest<ScimResource> updateRequest = new UpdateRequest<>(scimResourceId, original, scimResource, schemaRegistry);
        repository.update(updateRequest);
      } catch (UnresolvableOperationException unresolvableOperationException) {
        log.error("Could not complete final resolution pass, unresolvable bulkId", unresolvableOperationException);

        String detail = unresolvableOperationException.getLocalizedMessage();

        bulkOperationResult.setData(null);
        bulkOperationResult.setLocation(null);
        createAndSetErrorResponse(bulkOperationResult, Status.CONFLICT, detail);
        this.cleanup(bulkIdKey, transitiveReverseDependencies, bulkIdKeyToOperationResult);
      } catch (UnableToUpdateResourceException unableToUpdateResourceException) {
        log.error("Failed to update Scim Resource with resolved bulkIds", unableToUpdateResourceException);

        String detail = unableToUpdateResourceException.getLocalizedMessage();

        bulkOperationResult.setData(null);
        bulkOperationResult.setLocation(null);
        createAndSetErrorResponse(bulkOperationResult, unableToUpdateResourceException.getStatus(), detail);
        this.cleanup(bulkIdKey, transitiveReverseDependencies, bulkIdKeyToOperationResult);
      } catch (ResourceException e) {
        log.error("Could not complete final resolution pass, unresolvable bulkId", e);

        String detail = e.getLocalizedMessage();

        bulkOperationResult.setData(null);
        bulkOperationResult.setLocation(null);
        createAndSetErrorResponse(bulkOperationResult, Status.NOT_FOUND, detail);
        this.cleanup(bulkIdKey, transitiveReverseDependencies, bulkIdKeyToOperationResult);
      }
    }

    Status status = errorCountExceeded ? Status.BAD_REQUEST : Status.OK;

    response = new BulkResponse()
      .setOperations(bulkOperations)
      .setStatus(status);

    return Response.status(status)
      .entity(response)
      .build();
  }

  /**
   * Delete resources that depend on {@code bulkIdKeyToCleanup}, remove
   * {@link BulkOperation}s data, and set their code and response
   * 
   * @param bulkIdKeyToCleanup
   * @param transitiveReverseDependencies
   * @param bulkIdKeyToOperationResult
   */
  private void cleanup(String bulkIdKeyToCleanup, Map<String, Set<String>> transitiveReverseDependencies, Map<String, BulkOperation> bulkIdKeyToOperationResult) {
    Set<String> reverseDependencies = transitiveReverseDependencies.getOrDefault(bulkIdKeyToCleanup, Collections.emptySet());
    BulkOperation operationResult = bulkIdKeyToOperationResult.get(bulkIdKeyToCleanup);
    String bulkId = operationResult.getBulkId();
    ScimResource scimResource = operationResult.getData();
    @SuppressWarnings("unchecked")
    Class<ScimResource> scimResourceClass = (Class<ScimResource>) scimResource.getClass();
    Repository<ScimResource> repository = this.repositoryRegistry.getRepository(scimResourceClass);

    try {
      if (StringUtils.isNotBlank(scimResource.getId())) {
        repository.delete(scimResource.getId());
      }
    } catch (ResourceException unableToDeleteResourceException) {
      log.error("Could not delete ScimResource after failure: {}", scimResource);
    }
    for (String dependentBulkIdKey : reverseDependencies) {
      BulkOperation dependentOperationResult = bulkIdKeyToOperationResult.get(dependentBulkIdKey);

      if (!(dependentOperationResult.getResponse() instanceof ErrorResponse))
        try {
          ScimResource dependentResource = dependentOperationResult.getData();
          String dependentResourceId = dependentResource.getId();
          @SuppressWarnings("unchecked")
          Class<ScimResource> dependentResourceClass = (Class<ScimResource>) dependentResource.getClass();
          Repository<ScimResource> dependentResourceRepository = this.repositoryRegistry.getRepository(dependentResourceClass);

          dependentOperationResult.setData(null);
          dependentOperationResult.setLocation(null);
          createAndSetErrorResponse(dependentOperationResult, Status.CONFLICT, String.format(OPERATION_DEPENDS_ON_FAILED_OPERATION, bulkId, dependentBulkIdKey));
          dependentResourceRepository.delete(dependentResourceId);
        } catch (ResourceException unableToDeleteResourceException) {
          log.error("Could not delete depenedent ScimResource after failing to update dependee", unableToDeleteResourceException);
        }
    }
  }

  /**
   * Based on the method requested by {@code operationResult}, invoke that
   * method. Fill {@code unresolveds} with unresolved bulkIds and complexes that
   * contain unresolved bulkIds.
   * 
   * @param unresolveds
   * @param operationResult
   * @param bulkIdKeyToOperationResult
   * @param uriInfo
   * @throws UnableToCreateResourceException
   * @throws UnableToDeleteResourceException
   * @throws UnableToUpdateResourceException
   * @throws UnresolvableOperationException
   */
  private void handleBulkOperationMethod(List<IWishJavaHadTuples> unresolveds, BulkOperation operationResult, Map<String, BulkOperation> bulkIdKeyToOperationResult, UriInfo uriInfo) throws ResourceException, UnresolvableOperationException {
    ScimResource scimResource = operationResult.getData();
    Method bulkOperationMethod = operationResult.getMethod();
    String bulkId = operationResult.getBulkId();
    Class<ScimResource> scimResourceClass;

    if (scimResource == null) {
      String path = operationResult.getPath();
      String endPoint = path.substring(0, path.lastIndexOf('/'));
      Class<ScimResource> clazz = (Class<ScimResource>) schemaRegistry.findScimResourceClassFromEndpoint(endPoint);
      scimResourceClass = clazz;
    } else {
      @SuppressWarnings("unchecked")
      Class<ScimResource> clazz = (Class<ScimResource>) scimResource.getClass();
      scimResourceClass = clazz;
    }
    Repository<ScimResource> repository = repositoryRegistry.getRepository(scimResourceClass);

    switch (bulkOperationMethod) {
    case POST: {
      log.debug("POST: {}", scimResource);

      this.resolveTopLevel(unresolveds, operationResult, bulkIdKeyToOperationResult);

      log.debug("Creating {}", scimResource);

      ScimResource newScimResource = repository.create(scimResource);
      String bulkOperationPath = operationResult.getPath();
      String newResourceId = newScimResource.getId();
      String newResourceUri = uriInfo.getBaseUriBuilder()
                                     .path(bulkOperationPath)
                                     .path(newResourceId)
                                     .build()
                                     .toString();

      if (bulkId != null) {
        String bulkIdKey = "bulkId:" + bulkId;

        log.debug("adding {} = {}", bulkIdKey, newResourceId);
        bulkIdKeyToOperationResult.get(bulkIdKey)
                                  .setData(newScimResource);
      }
      operationResult.setData(newScimResource);
      operationResult.setLocation(newResourceUri);
      operationResult.setPath(null);
      operationResult.setStatus(StatusWrapper.wrap(Status.CREATED));
    }
      break;

    case DELETE: {
      log.debug("DELETE: {}", operationResult.getPath());

      String scimResourceId = operationResult.getPath()
                                             .substring(operationResult.getPath()
                                                                       .lastIndexOf("/")
                                                 + 1);

      repository.delete(scimResourceId);
      operationResult.setStatus(StatusWrapper.wrap(Status.NO_CONTENT));
    }
      break;

    case PUT: {
      log.debug("PUT: {}", scimResource);

      this.resolveTopLevel(unresolveds, operationResult, bulkIdKeyToOperationResult);
      String id = operationResult.getPath()
                                 .substring(operationResult.getPath()
                                                           .lastIndexOf("/")
                                     + 1);

      try {
        ScimResource original = repository.get(id);

        UpdateRequest<ScimResource> updateRequest = new UpdateRequest<>(id, original, scimResource, schemaRegistry);
        
        repository.update(updateRequest);
        operationResult.setStatus(StatusWrapper.wrap(Status.OK));
      } catch (UnableToRetrieveResourceException e) {
        operationResult.setStatus(StatusWrapper.wrap(Status.NOT_FOUND));
      }
    }
      break;

    default: {
      BulkOperation.Method method = operationResult.getMethod();
      String detail = "Method not allowed: " + method;

      log.error("Received unallowed method: {}", method);
      createAndSetErrorResponse(operationResult, Status.METHOD_NOT_ALLOWED, detail);
    }
      break;
    }
  }

  private static void createAndSetErrorResponse(BulkOperation operationResult, int statusCode, String detail) {
    createAndSetErrorResponse(operationResult, Status.fromStatusCode(statusCode), detail);
  }

  private static void createAndSetErrorResponse(BulkOperation operationResult, Status status, String detail) {
    ErrorResponse error = new ErrorResponse(status, detail);
    operationResult.setResponse(error);
    operationResult.setStatus(new StatusWrapper(status));
    operationResult.setPath(null);
  }

  @AllArgsConstructor
  private static class IWishJavaHadTuples {
    public final String bulkIdKey;
    public final List<UnresolvedTopLevel> unresolveds;
    public final BulkOperation bulkOperationResult;
  }

  private static class UnresolvableOperationException extends Exception {
    private static final long serialVersionUID = -6081994707016671935L;

    public UnresolvableOperationException(String message) {
      super(message);
    }
  }

  @AllArgsConstructor
  private static class UnresolvedComplex {
    private final Object object;
    private final Schema.AttributeAccessor accessor;
    private final String bulkIdKey;

    public void resolve(Map<String, BulkOperation> bulkIdKeyToOperationResult) throws UnresolvableOperationException {
      BulkOperation resolvedOperation = bulkIdKeyToOperationResult.get(this.bulkIdKey);
      BaseResource response = resolvedOperation.getResponse();
      ScimResource resolvedResource = resolvedOperation.getData();

      if ((response == null || !(response instanceof ErrorResponse)) && resolvedResource != null) {
        String resolvedId = resolvedResource.getId();
        this.accessor.set(this.object, resolvedId);
      } else {
        throw new UnresolvableOperationException(String.format(BULK_ID_REFERS_TO_FAILED_RESOURCE, this.bulkIdKey));
      }
    }
  }

  @AllArgsConstructor
  private static abstract class UnresolvedTopLevel {
    protected final Schema.AttributeAccessor accessor;

    public abstract void resolve(ScimResource scimResource, Map<String, BulkOperation> bulkIdKeyToOperationResult) throws UnresolvableOperationException;
  }

  private static class UnresolvedTopLevelBulkId extends UnresolvedTopLevel {
    private final String unresolvedBulkIdKey;

    public UnresolvedTopLevelBulkId(Schema.AttributeAccessor accessor, String bulkIdKey) {
      super(accessor);
      this.unresolvedBulkIdKey = bulkIdKey;
    }

    @Override
    public void resolve(ScimResource scimResource, Map<String, BulkOperation> bulkIdKeyToOperationResult) throws UnresolvableOperationException {
      BulkOperation resolvedOperationResult = bulkIdKeyToOperationResult.get(this.unresolvedBulkIdKey);
      BaseResource response = resolvedOperationResult.getResponse();
      ScimResource resolvedResource = resolvedOperationResult.getData();

      if ((response == null || !(response instanceof ErrorResponse)) && resolvedResource != null) {
        String resolvedId = resolvedResource.getId();

        super.accessor.set(scimResource, resolvedId);
      } else {
        throw new UnresolvableOperationException("Bulk ID cannot be resolved because the resource it refers to had failed to be created: " + this.unresolvedBulkIdKey);
      }
    }
  }

  private static class UnresolvedTopLevelComplex extends UnresolvedTopLevel {
    public final Object complex;
    public final List<UnresolvedComplex> unresolveds;

    public UnresolvedTopLevelComplex(Schema.AttributeAccessor accessor, Object complex, List<UnresolvedComplex> unresolveds) {
      super(accessor);
      this.complex = complex;
      this.unresolveds = unresolveds;
    }

    @Override
    public void resolve(ScimResource scimResource, Map<String, BulkOperation> bulkIdKeyToOperationResult) throws UnresolvableOperationException {
      for (UnresolvedComplex unresolved : this.unresolveds) {
        unresolved.resolve(bulkIdKeyToOperationResult);
      }
      this.accessor.set(scimResource, this.complex);
    }
  }

  /**
   * Search through the subattribute {@code subAttributeValue} and fill
   * {@code unresolveds} with unresolved bulkIds.
   * 
   * @param unresolveds
   * @param attributeValue
   * @param attribute
   * @param bulkIdKeyToOperationResult
   * @return
   * @throws UnresolvableOperationException
   */
  private static List<UnresolvedComplex> resolveAttribute(List<UnresolvedComplex> unresolveds, Object attributeValue, Schema.Attribute attribute, Map<String, BulkOperation> bulkIdKeyToOperationResult) throws UnresolvableOperationException {
    if (attributeValue == null) {
      return unresolveds;
    }
    List<Schema.Attribute> attributes = attribute.getAttributes();

    for (Schema.Attribute subAttribute : attributes) {
      Schema.AttributeAccessor accessor = subAttribute.getAccessor();

      if (subAttribute.isScimResourceIdReference()) {
        // TODO - This will fail if field is a char or Character array
        String bulkIdKey = accessor.get(attributeValue);

        if (bulkIdKey != null && bulkIdKey.startsWith("bulkId:")) {
          log.debug("Found bulkId: {}", bulkIdKey);
          if (bulkIdKeyToOperationResult.containsKey(bulkIdKey)) {
            BulkOperation resolvedOperationResult = bulkIdKeyToOperationResult.get(bulkIdKey);
            BaseResource response = resolvedOperationResult.getResponse();
            ScimResource resolvedResource = resolvedOperationResult.getData();

            if ((response == null || !(response instanceof ErrorResponse)) && resolvedResource != null && resolvedResource.getId() != null) {
              String resolvedId = resolvedResource.getId();

              accessor.set(attributeValue, resolvedId);
            } else {
              UnresolvedComplex unresolved = new UnresolvedComplex(attributeValue, accessor, bulkIdKey);

              unresolveds.add(unresolved);
            }
          } else {
            throw new UnresolvableOperationException(String.format(BULK_ID_DOES_NOT_EXIST, bulkIdKey));
          }
        }
      } else if (subAttribute.getType() == Schema.Attribute.Type.COMPLEX) {
        Object subFieldValue = accessor.get(attributeValue);

        if (subFieldValue != null) {
          Class<?> subFieldClass = subFieldValue.getClass();
          boolean isCollection = Collection.class.isAssignableFrom(subFieldClass);

          if (isCollection || subFieldClass.isArray()) {
            @SuppressWarnings("unchecked")
            Collection<Object> subFieldValues = isCollection ? (Collection<Object>) subFieldValue : Arrays.asList((Object[]) subFieldValue);

            for (Object subArrayFieldValue : subFieldValues) {
              resolveAttribute(unresolveds, subArrayFieldValue, subAttribute, bulkIdKeyToOperationResult);
            }
          } else {
            resolveAttribute(unresolveds, subFieldValue, subAttribute, bulkIdKeyToOperationResult);
          }
        }
      }
    }
    log.debug("Resolved attribute had {} unresolved fields", unresolveds.size());
    return unresolveds;
  }

  /**
   * Attempt to resolve the bulkIds referenced inside of the
   * {@link ScimResource} contained inside of {@code bulkOperationResult}. Fill
   * {@code unresolveds} with bulkIds that could not be yet resolved.
   * 
   * @param unresolveds
   * @param bulkOperationResult
   * @param bulkIdKeyToOperationResult
   * @throws UnresolvableOperationException
   */
  private void resolveTopLevel(List<IWishJavaHadTuples> unresolveds, BulkOperation bulkOperationResult, Map<String, BulkOperation> bulkIdKeyToOperationResult) throws UnresolvableOperationException {
    ScimResource scimResource = bulkOperationResult.getData();
    String schemaUrn = scimResource.getBaseUrn();
    Schema schema = this.schemaRegistry.getSchema(schemaUrn);
    List<UnresolvedTopLevel> unresolvedTopLevels = new ArrayList<>();

    for (Schema.Attribute attribute : schema.getAttributes()) {
      Schema.AttributeAccessor accessor = attribute.getAccessor();

      if (attribute.isScimResourceIdReference()) {
        String bulkIdKey = accessor.get(scimResource);

        if (bulkIdKey != null && bulkIdKey.startsWith("bulkId:")) {
          if (bulkIdKeyToOperationResult.containsKey(bulkIdKey)) {
            BulkOperation resolvedOperationResult = bulkIdKeyToOperationResult.get(bulkIdKey);
            BaseResource response = resolvedOperationResult.getResponse();
            ScimResource resolvedResource = resolvedOperationResult.getData();

            if ((response == null || !(response instanceof ErrorResponse)) && resolvedResource != null) {
              String resolvedId = resolvedResource.getId();

              accessor.set(scimResource, resolvedId);
            } else {
              UnresolvedTopLevel unresolved = new UnresolvedTopLevelBulkId(accessor, bulkIdKey);

              accessor.set(scimResource, null);
              unresolvedTopLevels.add(unresolved);
            }
          } else {
            throw new UnresolvableOperationException(String.format(BULK_ID_DOES_NOT_EXIST, bulkIdKey));
          }
        }
      } else if (attribute.getType() == Schema.Attribute.Type.COMPLEX) {
        Object attributeFieldValue = accessor.get(scimResource);

        if (attributeFieldValue != null) {
          List<UnresolvedComplex> subUnresolveds = new ArrayList<>();
          Class<?> subFieldClass = attributeFieldValue.getClass();
          boolean isCollection = Collection.class.isAssignableFrom(subFieldClass);

          if (isCollection || subFieldClass.isArray()) {
            @SuppressWarnings("unchecked")
            Collection<Object> subFieldValues = isCollection ? (Collection<Object>) attributeFieldValue : Arrays.asList((Object[]) attributeFieldValue);

            for (Object subArrayFieldValue : subFieldValues) {
              resolveAttribute(subUnresolveds, subArrayFieldValue, attribute, bulkIdKeyToOperationResult);
            }
          } else {
            resolveAttribute(subUnresolveds, attributeFieldValue, attribute, bulkIdKeyToOperationResult);
          }

          if (subUnresolveds.size() > 0) {
            UnresolvedTopLevel unresolved = new UnresolvedTopLevelComplex(accessor, attributeFieldValue, subUnresolveds);

            accessor.set(scimResource, null);
            unresolvedTopLevels.add(unresolved);
          }
        }
      }
    }
    if (unresolvedTopLevels.size() > 0) {
      String bulkIdKey = "bulkId:" + bulkOperationResult.getBulkId();

      unresolveds.add(new IWishJavaHadTuples(bulkIdKey, unresolvedTopLevels, bulkOperationResult));
    }
  }

  /**
   * Traverse the provided dependency graph and fill {@code visited} with
   * visited bulkIds.
   * 
   * @param visited
   * @param dependencyGraph
   * @param root
   * @param current
   */
  private static void generateVisited(Set<String> visited, Map<String, Set<String>> dependencyGraph, String root, String current) {
    if (!root.equals(current) && !visited.contains(current)) {
      visited.add(current);

      Set<String> dependencies = dependencyGraph.getOrDefault(current, Collections.emptySet());
      for (String dependency : dependencies) {
        generateVisited(visited, dependencyGraph, root, dependency);
      }
    }
  }

  /**
   * If A -> {B} and B -> {C} then A -> {B, C}.
   * 
   * @param dependenciesGraph
   * @return
   */
  private static Map<String, Set<String>> generateTransitiveDependenciesGraph(Map<String, Set<String>> dependenciesGraph) {
    Map<String, Set<String>> transitiveDependenciesGraph = new HashMap<>();

    for (Map.Entry<String, Set<String>> entry : dependenciesGraph.entrySet()) {
      String root = entry.getKey();
      Set<String> dependencies = entry.getValue();
      Set<String> visited = new HashSet<>();

      transitiveDependenciesGraph.put(root, visited);

      for (String dependency : dependencies) {
        generateVisited(visited, dependenciesGraph, root, dependency);
      }
    }
    return transitiveDependenciesGraph;
  }

  private static void generateReverseDependenciesGraph(Map<String, Set<String>> reverseDependenciesGraph, String dependentBulkId, Object scimObject, List<Schema.Attribute> scimObjectAttributes) {
    for (Schema.Attribute scimObjectAttribute : scimObjectAttributes)
      if (scimObjectAttribute.isScimResourceIdReference()) {
        String reference = scimObjectAttribute.getAccessor().get(scimObject);

        if (reference != null && reference.startsWith("bulkId:")) {
          Set<String> dependents = reverseDependenciesGraph.computeIfAbsent(reference, (unused) -> new HashSet<>());

          dependents.add("bulkId:" + dependentBulkId);
        }
      } else if (scimObjectAttribute.isMultiValued()) { // all multiValueds
                                                        // are COMPLEX, not
                                                        // all COMPLEXES are
                                                        // multiValued
        Object attributeObject = scimObjectAttribute.getAccessor().get(scimObject);
        if (attributeObject != null) {
          Class<?> attributeObjectClass = attributeObject.getClass();
          boolean isCollection = Collection.class.isAssignableFrom(attributeObjectClass);
          Collection<?> attributeValues = isCollection ? (Collection<?>) attributeObject : List.of(attributeObject);
          List<Schema.Attribute> subAttributes = scimObjectAttribute.getAttributes();

          for (Object attributeValue : attributeValues) {
            generateReverseDependenciesGraph(reverseDependenciesGraph, dependentBulkId, attributeValue, subAttributes);
          }
        }
      } else if (scimObjectAttribute.getType() == Schema.Attribute.Type.COMPLEX) {
        Object attributeValue = scimObjectAttribute.getAccessor().get(scimObject);
        List<Schema.Attribute> subAttributes = scimObjectAttribute.getAttributes();

        generateReverseDependenciesGraph(reverseDependenciesGraph, dependentBulkId, attributeValue, subAttributes);
      }
  }

  /**
   * Finds the reverse dependencies of each {@link BulkOperation}.
   * 
   * @param bulkOperations
   * @return
   */
  private Map<String, Set<String>> generateReverseDependenciesGraph(List<BulkOperation> bulkOperations) {
    Map<String, Set<String>> reverseDependenciesGraph = new HashMap<>();

    for (BulkOperation bulkOperation : bulkOperations) {
      String bulkId = bulkOperation.getBulkId();

      if (bulkId != null) {
        ScimResource scimResource = bulkOperation.getData();
        String scimResourceBaseUrn = scimResource.getBaseUrn();
        Schema schema = this.schemaRegistry.getSchema(scimResourceBaseUrn);
        List<Schema.Attribute> attributes = schema.getAttributes();

        generateReverseDependenciesGraph(reverseDependenciesGraph, bulkId, scimResource, attributes);
      }
    }
    return reverseDependenciesGraph;
  }
}
