/*
* 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.client.rest;

import java.util.Optional;
import java.util.Set;
import java.util.function.Function;

import jakarta.ws.rs.ProcessingException;
import jakarta.ws.rs.client.Client;
import jakarta.ws.rs.client.Entity;
import jakarta.ws.rs.client.Invocation;
import jakarta.ws.rs.client.WebTarget;
import jakarta.ws.rs.core.GenericType;
import jakarta.ws.rs.core.Response;
import jakarta.ws.rs.core.Response.Status;

import org.apache.directory.scim.protocol.adapter.FilterWrapper;
import org.apache.directory.scim.spec.annotation.ScimResourceType;
import org.apache.directory.scim.protocol.BaseResourceTypeResource;
import org.apache.directory.scim.protocol.Constants;
import org.apache.directory.scim.spec.filter.attribute.AttributeReference;
import org.apache.directory.scim.spec.filter.attribute.AttributeReferenceListWrapper;
import org.apache.directory.scim.protocol.data.ErrorResponse;
import org.apache.directory.scim.protocol.data.ListResponse;
import org.apache.directory.scim.protocol.data.PatchRequest;
import org.apache.directory.scim.protocol.data.SearchRequest;
import org.apache.directory.scim.protocol.exception.ScimException;
import org.apache.directory.scim.spec.filter.Filter;
import org.apache.directory.scim.spec.filter.SortOrder;
import org.apache.directory.scim.spec.resources.ScimResource;

public abstract class BaseScimClient<T extends ScimResource> implements AutoCloseable {

  static final String ATTRIBUTES_QUERY_PARAM = "attributes";
  static final String EXCLUDED_ATTRIBUTES_QUERY_PARAM = "excludedAttributes";

  private final Client client;
  private final Class<T> scimResourceClass;
  private final GenericType<ListResponse<T>> scimResourceListResponseGenericType;
  private final WebTarget target;
  private final InternalScimClient scimClient;
  private RestCall invoke = Invocation::invoke;

  public BaseScimClient(Client client, String baseUrl, Class<T> scimResourceClass, GenericType<ListResponse<T>> scimResourceListGenericType) {
    ScimResourceType scimResourceType = scimResourceClass.getAnnotation(ScimResourceType.class);
    String endpoint = scimResourceType != null ? scimResourceType.endpoint() : null;

    if (endpoint == null) {
      throw new IllegalArgumentException("scimResourceClass: " + scimResourceClass.getSimpleName() + " must have annotation " + ScimResourceType.class.getSimpleName() + " and annotation must have non-null endpoint");
    }
    this.client = client;
    this.scimResourceClass = scimResourceClass;
    this.scimResourceListResponseGenericType = scimResourceListGenericType;
    this.target = this.client.target(baseUrl).path(endpoint);
    this.scimClient = new InternalScimClient();
  }

  public BaseScimClient(Client client, String baseUrl, Class<T> scimResourceClass, GenericType<ListResponse<T>> scimResourceListGenericType, RestCall invoke) {
    this(client, baseUrl, scimResourceClass, scimResourceListGenericType);

    this.invoke = invoke;
  }

  @Override
  public void close() {
    this.client.close();
  }

  public Optional<T> getById(String id) throws ScimException {
    return this.getById(id, null, null);
  }

  public Optional<T> getById(String id, AttributeReferenceListWrapper attributes, AttributeReferenceListWrapper excludedAttributes) throws ScimException {
    Optional<T> resource;
    Response response = this.scimClient.getById(id, attributes, excludedAttributes);

    try {
      if (RestClientUtil.isSuccessful(response)) {
        resource = Optional.of(response.readEntity(this.scimResourceClass));
      } else if (response.getStatus() == Status.NOT_FOUND.getStatusCode()) {
        resource = Optional.empty();
      } else {
        ErrorResponse errorResponse = response.readEntity(ErrorResponse.class);

        throw new ScimException(errorResponse, Status.fromStatusCode(response.getStatus()));
      }
    } finally {
      RestClientUtil.close(response);
    }
    return resource;
  }

  public ListResponse<T> query(AttributeReferenceListWrapper attributes, AttributeReferenceListWrapper excludedAttributes, Filter filter, AttributeReference sortBy, SortOrder sortOrder, Integer startIndex, Integer count) throws ScimException {
    ListResponse<T> listResponse;
    FilterWrapper filterWrapper = new FilterWrapper(filter);
    Response response = this.scimClient.query(attributes, excludedAttributes, filterWrapper, sortBy, sortOrder, startIndex, count);
    listResponse = handleResponse(response, scimResourceListResponseGenericType, response::readEntity);

    return listResponse;
  }

  public T create(T resource) throws ScimException {
    return this.create(resource, null, null);
  }

  public T create(T resource, AttributeReferenceListWrapper attributes, AttributeReferenceListWrapper excludedAttributes) throws ScimException {
    Response response = this.scimClient.create(resource, attributes, excludedAttributes);
    
    return handleResponse(response, scimResourceClass, response::readEntity);
  }

  public ListResponse<T> find(SearchRequest searchRequest) throws ScimException {
    ListResponse<T> listResponse;
    Response response = this.scimClient.find(searchRequest);
    listResponse = handleResponse(response, scimResourceListResponseGenericType, response::readEntity);

    return listResponse;
  }

  public T update(String id, T resource) throws ScimException {
    return this.update(id, resource, null, null);
  }

  public T update(String id, T resource, AttributeReferenceListWrapper attributes, AttributeReferenceListWrapper excludedAttributes) throws ScimException {
    Response response = this.scimClient.update(resource, id, attributes, excludedAttributes);

    return handleResponse(response, scimResourceClass, response::readEntity);
  }

  public T patch(String id, PatchRequest patchRequest) throws ScimException {
    return this.patch(id, patchRequest, null, null);
  }
  
  public T patch(String id, PatchRequest patchRequest, AttributeReferenceListWrapper attributes, AttributeReferenceListWrapper excludedAttributes) throws ScimException {
    Response response = this.scimClient.patch(patchRequest, id, attributes, excludedAttributes);

    return handleResponse(response, scimResourceClass, response::readEntity);
  }

  public void delete(String id) throws ScimException {
    Response response = this.scimClient.delete(id);

    handleResponse(response);
  }

  static <E, T> E handleResponse(Response response, T type, Function<T, E> readEntity) throws ScimException {
    E entity;

    try {
      if (RestClientUtil.isSuccessful(response)) {
        entity = readEntity.apply(type);
      } else {
        Status status = Status.fromStatusCode(response.getStatus());
        ErrorResponse errorResponse = response.readEntity(ErrorResponse.class);

        throw new ScimException(errorResponse, status);
      }
    } finally {
      RestClientUtil.close(response);
    }
    return entity;
  }

  static void handleResponse(Response response) throws ScimException {
    try {
      if (!RestClientUtil.isSuccessful(response)) {
        Status status = Status.fromStatusCode(response.getStatus());
        ErrorResponse errorResponse = response.readEntity(ErrorResponse.class);

        throw new ScimException(errorResponse, status);
      }
    } catch (ProcessingException e) {
      ErrorResponse er = new ErrorResponse(Status.INTERNAL_SERVER_ERROR, e.getMessage());
      throw new ScimException(er, Status.INTERNAL_SERVER_ERROR);
    } finally {
      RestClientUtil.close(response);
    }
  }

  static ScimException toScimException(RestException restException) {
    return new ScimException(restException.getError(), restException.getStatus());
  }

  public RestCall getInvoke() {
    return this.invoke;
  }

  public void setInvoke(RestCall invoke) {
    this.invoke = invoke;
  }

  private class InternalScimClient implements BaseResourceTypeResource<T> {

    private static final String FILTER_QUERY_PARAM = "filter";
    private static final String SORT_BY_QUERY_PARAM = "sortBy";
    private static final String SORT_ORDER_QUERY_PARAM = "sortOrder";
    private static final String START_INDEX_QUERY_PARAM = "startIndex";
    private static final String COUNT_QUERY_PARAM = "count";

    @Override
    public Response getById(String id, AttributeReferenceListWrapper attributes, AttributeReferenceListWrapper excludedAttributes) throws ScimException {
      Response response;
      Invocation request = BaseScimClient.this.target
          .path(id)
          .queryParam(ATTRIBUTES_QUERY_PARAM, nullOutQueryParamIfListIsNullOrEmpty(attributes))
          .queryParam(EXCLUDED_ATTRIBUTES_QUERY_PARAM, nullOutQueryParamIfListIsNullOrEmpty(excludedAttributes))
          .request(getContentType())
          .buildGet();

      try {
        response = BaseScimClient.this.invoke.apply(request);

        return response;
      } catch (RestException restException) {
        throw toScimException(restException);
      }
    }

    @Override
    public Response query(AttributeReferenceListWrapper attributes, AttributeReferenceListWrapper excludedAttributes, FilterWrapper filter, AttributeReference sortBy, SortOrder sortOrder, Integer startIndex, Integer count) throws ScimException {
      Response response;
      Invocation request = BaseScimClient.this.target
          .queryParam(ATTRIBUTES_QUERY_PARAM, nullOutQueryParamIfListIsNullOrEmpty(attributes))
          .queryParam(EXCLUDED_ATTRIBUTES_QUERY_PARAM, nullOutQueryParamIfListIsNullOrEmpty(excludedAttributes))
          .queryParam(FILTER_QUERY_PARAM, filter.getFilter())
          .queryParam(SORT_BY_QUERY_PARAM, sortBy)
          .queryParam(SORT_ORDER_QUERY_PARAM, sortOrder != null ? sortOrder.name() : null)
          .queryParam(START_INDEX_QUERY_PARAM, startIndex)
          .queryParam(COUNT_QUERY_PARAM, count)
          .request(getContentType())
          .buildGet();

      try {
        response = BaseScimClient.this.invoke.apply(request);

        return response;
      } catch (RestException restException) {
        throw toScimException(restException);
      }
    }

    @Override
    public Response create(T resource, AttributeReferenceListWrapper attributes, AttributeReferenceListWrapper excludedAttributes) throws ScimException {
      Response response;
      Invocation request = BaseScimClient.this.target
          .queryParam(ATTRIBUTES_QUERY_PARAM, nullOutQueryParamIfListIsNullOrEmpty(attributes))
          .queryParam(EXCLUDED_ATTRIBUTES_QUERY_PARAM, nullOutQueryParamIfListIsNullOrEmpty(excludedAttributes))
          .request(getContentType())
          .buildPost(Entity.entity(resource, getContentType()));

      try {
        response = BaseScimClient.this.invoke.apply(request);

        return response;
      } catch (RestException restException) {
        throw toScimException(restException);
      }
    }

    @Override
    public Response find(SearchRequest searchRequest) throws ScimException {
      Response response;
      Invocation request = BaseScimClient.this.target
          .path(".search")
          .request(getContentType())
          .buildPost(Entity.entity(searchRequest, getContentType()));

      try {
        response = BaseScimClient.this.invoke.apply(request);

        return response;
      } catch (RestException restException) {
        throw toScimException(restException);
      }
    }

    @Override
    public Response update(T resource, String id, AttributeReferenceListWrapper attributes, AttributeReferenceListWrapper excludedAttributes) throws ScimException {
      Response response;
      Invocation request = BaseScimClient.this.target
          .path(id)
          .queryParam(ATTRIBUTES_QUERY_PARAM, nullOutQueryParamIfListIsNullOrEmpty(attributes))
          .queryParam(EXCLUDED_ATTRIBUTES_QUERY_PARAM, nullOutQueryParamIfListIsNullOrEmpty(excludedAttributes))
          .request(getContentType())
          .buildPut(Entity.entity(resource, getContentType()));

      try {
        response = BaseScimClient.this.invoke.apply(request);

        return response;
      } catch (RestException restException) {
        throw toScimException(restException);
      }
    }

    @Override
    public Response patch(PatchRequest patchRequest, String id, AttributeReferenceListWrapper attributes, AttributeReferenceListWrapper excludedAttributes) throws ScimException {
      Response response;
      Invocation request = BaseScimClient.this.target
          .path(id)
          .queryParam(ATTRIBUTES_QUERY_PARAM, nullOutQueryParamIfListIsNullOrEmpty(attributes))
          .queryParam(EXCLUDED_ATTRIBUTES_QUERY_PARAM, nullOutQueryParamIfListIsNullOrEmpty(excludedAttributes))
          .request(getContentType())
          .build("PATCH", Entity.entity(patchRequest, getContentType()));

      try {
        response = BaseScimClient.this.invoke.apply(request);

        return response;
      } catch (RestException restException) {
        throw toScimException(restException);
      }
    }

    @Override
    public Response delete(String id) throws ScimException {
      Response response;
      Invocation request = BaseScimClient.this.target
          .path(id)
          .request(getContentType())
          .buildDelete();

      try {
        response = BaseScimClient.this.invoke.apply(request);

        return response;
      } catch (RestException restException) {
        throw toScimException(restException);
      }
    }
    
    private AttributeReferenceListWrapper nullOutQueryParamIfListIsNullOrEmpty(AttributeReferenceListWrapper wrapper) {
      if (wrapper == null) {
        return null;
      }
      Set<AttributeReference> attributeReferences = wrapper.getAttributeReferences();
      if (attributeReferences == null || attributeReferences.isEmpty()) {
        return null;
      }
      
      return wrapper;
    }
  }

  protected String getContentType() {
    return Constants.SCIM_CONTENT_TYPE;
  }
}
