package eu.dnetlib.broker.common.clients;

import java.util.Date;
import java.util.Objects;

import org.apache.lucene.search.join.ScoreMode;
import org.elasticsearch.action.search.SearchType;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.elasticsearch.annotations.Document;
import org.springframework.data.elasticsearch.core.ElasticsearchOperations;
import org.springframework.data.elasticsearch.core.SearchHit;
import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates;
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.data.util.CloseableIterator;

import eu.dnetlib.broker.common.elasticsearch.Event;
import eu.dnetlib.broker.common.subscriptions.MapCondition;
import eu.dnetlib.broker.common.subscriptions.NotificationFrequency;
import eu.dnetlib.broker.common.subscriptions.NotificationMode;
import eu.dnetlib.broker.common.subscriptions.Subscription;
import eu.dnetlib.broker.common.utils.DateParser;

@Disabled
// @RunWith(SpringJUnit4ClassRunner.class)
// @ContextConfiguration(locations = { "classpath:/applicationContext-test-queries.xml" })
public class IndexClientTest {

	private static final String topic = "ENRICH/MORE/PID";
	private static final Date fromDate = DateParser.parse("2016-01-31");

	private static final String indexName = Event.class.getAnnotation(Document.class).indexName();

	@Autowired
	private ElasticsearchOperations esOperations;

	@Test
	public void testSearchTopic() {
		System.out.println("Start searching");

		final NativeSearchQuery searchQuery = new NativeSearchQueryBuilder()
			.withQuery(QueryBuilders.boolQuery()
				.must(QueryBuilders.matchQuery("topic", topic))
				.must(QueryBuilders.rangeQuery("creationDate").from(fromDate)))
			.withSearchType(SearchType.DEFAULT)
			.withPageable(PageRequest.of(0, 10))
			.build();

		int count = 0;
		final CloseableIterator<SearchHit<Event>> it = esOperations.searchForStream(searchQuery, Event.class, IndexCoordinates.of(indexName));

		while (it.hasNext()) {
			System.out.println(" > " + it.next());
			count++;
		}
		System.out.println("SIZE: " + count);

	}

	@Test
	@Disabled
	public void testSearchSubscription() {
		System.out.println("Start searching");

		final Subscription s = new Subscription();
		s.setSubscriptionId("sub-db0b35d4-1b0f-4660-a849-34fbec8fb6f7");
		s.setSubscriber("artini@isti.cnr.it");
		s.setTopic("ENRICH/MORE/OPENACCESS_VERSION");
		s.setFrequency(NotificationFrequency.daily);
		s.setMode(NotificationMode.MOCK);
		s.setConditions("[{\"field\":\"targetDatasourceName\",\"fieldType\":\"STRING\",\"operator\":\"EXACT\",\"listParams\":[{\"value\":\"Research Papers in Economics\"}]},{\"field\":\"trust\",\"fieldType\":\"FLOAT\",\"operator\":\"RANGE\",\"listParams\":[{\"value\":\"0\",\"otherValue\":\"1\"}]}]");

		final BoolQueryBuilder mapQuery = QueryBuilders.boolQuery();

		s.getConditionsAsList()
			.stream()
			.map(MapCondition::asQueryBuilder)
			.filter(Objects::nonNull)
			.forEach(mapQuery::must);

		final NativeSearchQuery searchQuery = new NativeSearchQueryBuilder()
			.withQuery(QueryBuilders.boolQuery()
				.must(QueryBuilders.matchQuery("topic", s.getTopic()))
				.must(QueryBuilders.rangeQuery("creationDate").from(s.getLastNotificationDate()))
				.must(QueryBuilders.nestedQuery("map", mapQuery, ScoreMode.None)))
			.withSearchType(SearchType.DEFAULT)

			.withPageable(PageRequest.of(0, 10))
			.build();

		int count = 0;
		final CloseableIterator<SearchHit<Event>> it = esOperations.searchForStream(searchQuery, Event.class, IndexCoordinates.of(indexName));
		while (it.hasNext()) {
			System.out.println(" > " + it.next());
			count++;
		}
		System.out.println("SIZE: " + count);

	}
}
