package eu.dnetlib.datasource.publisher.clients;

import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import com.google.common.collect.Iterables;
import eu.dnetlib.data.index.CloudIndexClient;
import eu.dnetlib.data.index.CloudIndexClientException;

import eu.dnetlib.data.index.CloudIndexClientFactory;
import eu.dnetlib.datasource.publisher.ApiException;
import eu.dnetlib.datasource.publisher.clients.utils.DatasourceFunctions;
import eu.dnetlib.datasource.publisher.clients.utils.IndexDsInfo;
import eu.dnetlib.datasource.publisher.clients.utils.IndexRecordsInfo;
import eu.dnetlib.miscutils.functional.hash.Hashing;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.time.DateFormatUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.solr.client.solrj.response.QueryResponse;
import org.apache.solr.common.SolrDocument;
import org.springframework.http.HttpStatus;

/**
 * Created by claudio on 20/10/2016.
 */
public class DatasourceIndexClient {

	private static final Log log = LogFactory.getLog(DatasourceIndexClient.class);

	public static final String SEPARATOR = "::";
	public static final String DSVERSION = "__dsversion";

	private static Map<String, CloudIndexClient> indexClientMap = new ConcurrentHashMap<>();

	public IndexRecordsInfo getIndexInfo(final String dsId, final IndexDsInfo info) throws ApiException {
		try {
			final String collectedFrom = StringUtils.substringBefore(dsId, SEPARATOR) + SEPARATOR + Hashing.md5(StringUtils.substringAfter(dsId, SEPARATOR));
			final CloudIndexClient indexClient = getIndexClient(info);
			final String query = String.format("oaftype:result AND deletedbyinference:false AND collectedfromdatasourceid:\"%s\"", collectedFrom);
			log.debug(String.format("query on %s: %s", info.getFormat(), query));

			final QueryResponse rsp = indexClient.query(query, 1);

			long count = rsp.getResults().getNumFound();
			final SolrDocument doc = Iterables.getFirst(rsp.getResults(), new SolrDocument());
			if (log.isDebugEnabled()) {
				log.debug(String.format("got document %s", doc.toString()));
			}
			if (doc.isEmpty()) {
				throw new ApiException(HttpStatus.INTERNAL_SERVER_ERROR.value(), String.format("cannot find document matching query: %s", query));
			}
			final String date = getDate(doc);

			return new IndexRecordsInfo(count, date);
		} catch (final Throwable e) {
			throw new ApiException(HttpStatus.INTERNAL_SERVER_ERROR.value(), "Error querying publications from: " + dsId, e);
		}
	}

	private String getDate(final SolrDocument doc) throws ApiException {
		final List<Date> dsversion = (List<Date>) doc.get(DSVERSION);
		if (dsversion == null || dsversion.isEmpty()) {
			throw new ApiException(HttpStatus.INTERNAL_SERVER_ERROR.value(), String.format("cannot find %s in matched solr document", DSVERSION));
		}
		final Date date = Iterables.getLast(dsversion);

		return DateFormatUtils.format(date, DatasourceFunctions.DATE_FORMAT);
	}

	public String getLastIndexingDate(final IndexDsInfo info) throws ApiException {
		try {
			final QueryResponse rsp = getIndexClient(info).query("oaftype:datasource", 1);
			final SolrDocument doc = Iterables.getFirst(rsp.getResults(), null);
			final String dsversion = doc.get("__dsversion").toString();
			return StringUtils.substringBefore(dsversion, "T");
		} catch (CloudIndexClientException e) {
			throw new ApiException(HttpStatus.INTERNAL_SERVER_ERROR.value(), "Error querying index DS profile: " + info, e);
		}
	}

	private synchronized CloudIndexClient getIndexClient(final IndexDsInfo info) throws CloudIndexClientException {
		if (!indexClientMap.containsKey(info.getColl())) {
			indexClientMap.put(info.getColl(), CloudIndexClientFactory.newIndexClient(info.getIndexBaseUrl(), info.getColl(), false));
		}
		return indexClientMap.get(info.getColl());
	}

}
