package ca.uhn.fhir.jpa.search.elastic;

import ca.uhn.fhir.context.ConfigurationException;
import org.hibernate.search.backend.elasticsearch.cfg.ElasticsearchBackendSettings;
import org.hibernate.search.engine.cfg.BackendSettings;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.junit.jupiter.MockitoExtension;

import java.util.Properties;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.is;
import static org.junit.jupiter.api.Assertions.fail;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.spy;

@ExtendWith(MockitoExtension.class)
class ElasticsearchHibernatePropertiesBuilderTest {

	ElasticsearchHibernatePropertiesBuilder myPropertiesBuilder = spy(ElasticsearchHibernatePropertiesBuilder.class);

	@BeforeEach
	public void prepMocks() {
		//ensures we don't try to reach out to a real ES server on apply.
		doNothing().when(myPropertiesBuilder).injectStartupTemplate(any(), any(), any(), any());
	}

	@Test
	public void testRestUrlCannotContainProtocol() {
		String host = "localhost:9200";
		String protocolHost = "https://" + host;
		String failureMessage = "Elasticsearch URL cannot include a protocol, that is a separate property. Remove http:// or https:// from this URL.";

		myPropertiesBuilder
			.setProtocol("https")
			.setUsername("whatever")
			.setPassword("whatever");

		//SUT
		try {
			myPropertiesBuilder.setHosts(protocolHost);
			fail();
		} catch (ConfigurationException e ) {
			assertThat(e.getMessage(), is(equalTo(failureMessage)));
		}

		Properties properties = new Properties();
		myPropertiesBuilder
			.setHosts(host)
			.apply(properties);

		assertThat(properties.getProperty(BackendSettings.backendKey(ElasticsearchBackendSettings.HOSTS)), is(equalTo(host)));

	}

}

@@ -967,211 +967,8 @@
 );%0A%0A
-%09@BeforeEach%0A%09public void prepMocks() %7B%0A%09%09//ensures we don't try to reach out to a real ES server on apply.%0A%09%09doNothing().when(myPropertiesBuilder).injectStartupTemplate(any(), any(), any(), any());%0A%09%7D%0A%0A
 %09@Te
@@ -991,15 +991,13 @@
 test
-RestUrl
+Hosts
 Cann
@@ -1139,16 +1139,17 @@
 arch URL
+s
  cannot 
@@ -1408,16 +1408,45 @@
 colHost)
+%0A%09%09%09%09.apply(new Properties())
 ;%0A%09%09%09fai
@@ -1555,16 +1555,107 @@
 );%0A%09%09%7D%0A%0A
+%09%09doNothing().when(myPropertiesBuilder).injectStartupTemplate(any(), any(), any(), any());%0A
 %09%09Proper
@@ -1881,10 +1881,584 @@
 );%0A%0A%09%7D%0A%0A
+%09@Test%0A%09public void testHostsValueValidation() %7B%0A%09%09String host = %22localhost_9200,localhost:9201,localhost:9202%22;%0A%09%09String failureMessage = %22Elasticsearch URLs have to contain ':' as a host:port separator. Example: localhost:9200,localhost:9201,localhost:9202%22;%0A%0A%09%09myPropertiesBuilder%0A%09%09%09.setProtocol(%22https%22)%0A%09%09%09.setHosts(host)%0A%09%09%09.setUsername(%22whatever%22)%0A%09%09%09.setPassword(%22whatever%22);%0A%0A%09%09//SUT%0A%09%09try %7B%0A%09%09%09myPropertiesBuilder%0A%09%09%09%09.apply(new Properties());%0A%09%09%09fail();%0A%09%09%7D catch (ConfigurationException e ) %7B%0A%09%09%09assertThat(e.getMessage(), is(equalTo(failureMessage)));%0A%09%09%7D%0A%09%7D%0A%0A
 %7D%0A

Add test for validation of multiple hosts in ElasticsearchHibernatePropertiesBuilder