package org.sis.connector.solr.api;

import com.google.gson.Gson;
import org.json.simple.JSONObject;
import org.sis.connector.solr.cluster.ClusterState;
import org.sis.connector.solr.cluster.CollectionConfig;
import org.sis.connector.solr.cluster.SolrNode;
import org.sis.connector.solr.cluster.config.HandlersInfo;
import org.sis.repl.bindings.operations.SaveDocument;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.stereotype.Component;
import org.springframework.web.client.AsyncRestOperations;
import org.springframework.web.util.UriComponents;
import org.springframework.web.util.UriComponentsBuilder;

import java.util.Map;
import java.util.concurrent.CompletableFuture;

import static com.google.common.collect.ImmutableList.of;
import static org.sis.util.concurrent.Futures.completableFuture;
import static org.springframework.http.MediaType.APPLICATION_JSON;

@Component
public class SolrDocumentServiceImpl implements SolrDocumentService {
  private static final Logger LOGGER = LoggerFactory.getLogger(SolrDocumentServiceImpl.class);
  private static final Gson GSON = new Gson();

  private final AsyncRestOperations asyncRestOperations;
  private final ClusterState clusterState;

  @Autowired
  public SolrDocumentServiceImpl(AsyncRestOperations asyncRestOperations, ClusterState clusterState) {
    this.asyncRestOperations = asyncRestOperations;
    this.clusterState = clusterState;
  }

  @Override
  public CompletableFuture<JSONObject> save(SaveDocument operation) {
    UriComponents uriComponents = UriComponentsBuilder
        .fromHttpUrl(getSearchHandlerEndpoint(operation.getCollectionName()))
        .queryParam("wt", "json")
        .build();
    String payload = GSON.toJson(operation.getDocument());

    return sendAsyncRequest(payload, uriComponents.toUriString());
  }

  private CompletableFuture<JSONObject> sendAsyncRequest(String uri, String payload) {
    HttpHeaders httpHeaders = new HttpHeaders();
    httpHeaders.setAccept(of(APPLICATION_JSON));

    return completableFuture(asyncRestOperations.exchange(uri, HttpMethod.POST, new HttpEntity<>(payload, httpHeaders), Map.class))
        .thenApply(r -> new JSONObject(r.getBody()));
  }

  private String getSearchHandlerEndpoint(String collectionName) {
    String searchHandler = clusterState.findCollectionConfigByName(collectionName)
        .map(CollectionConfig::getHandlersInfo)
        .map(HandlersInfo::getSearchHandler)
        .orElseThrow(() -> {
          LOGGER.warn("Could not find any collection with name: '{}'", collectionName);
          return new IllegalStateException();
        });

    return clusterState.findLeaderNodeForCollection(collectionName)
        .map(SolrNode::getHost)
        .map(host -> String.format("%s/%s", host, searchHandler))
        .orElseThrow(() -> {
          LOGGER.warn("Could not find leader node for collection '{}'", collectionName);
          return new IllegalStateException();
        });
  }
}

@@ -576,52 +576,8 @@
 rs;%0A
-import org.springframework.http.HttpMethod;%0A
 impo
@@ -1748,22 +1748,22 @@
 pUrl(get
-Search
+Update
 HandlerE
@@ -1802,16 +1802,129 @@
 ame()))%0A
+        .queryParam(%22commit%22, true)%0A        .queryParam(%22json.command%22, false)%0A        .queryParam(%22wt%22, %22json%22)%0A
         
@@ -2055,25 +2055,16 @@
 Request(
-payload, 
 uriCompo
@@ -2082,16 +2082,25 @@
 String()
+, payload
 );%0A  %7D%0A%0A
@@ -2283,16 +2283,66 @@
 _JSON));
+%0A    httpHeaders.setContentType(APPLICATION_JSON);
 %0A%0A    re
@@ -2388,37 +2388,25 @@
 ons.
-exchange(uri, HttpMethod.POST
+postForEntity(uri
 , ne
@@ -2534,22 +2534,22 @@
 ring get
-Search
+Update
 HandlerE
@@ -2746,14 +2746,14 @@
 :get
-Search
+Update
 Hand
@@ -2801,33 +2801,64 @@
    LOGGER.warn(%22
-C
+Inconsistent collection view - c
 ould not find an
@@ -3109,16 +3109,19 @@
 s/%25s
+/%25s
 %22, host,
  sea
@@ -3116,16 +3116,32 @@
 %22, host,
+ collectionName,
  searchH

Fix construction of update handler endpoint