package eu.dnetlib.openaire.info;

import static org.hamcrest.core.Is.is;
import static org.mockito.BDDMockito.given;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

import java.nio.charset.Charset;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.Arrays;
import java.util.stream.Collectors;

import org.assertj.core.util.Maps;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.MockMvc;

@SpringBootTest
@WebMvcTest(InfoController.class)
public class InfoControllerTest {

	public static final MediaType APPLICATION_JSON_UTF8 = new MediaType(
		MediaType.APPLICATION_JSON.getType(),
		MediaType.APPLICATION_JSON.getSubtype(),
		Charset.forName("utf8"));

	@Autowired
	private MockMvc mvc;

	@MockBean
	private InfoController infoController;

	private LocalDate expectedDate;
	private String formattedDate;

	@BeforeEach
	public void setup() {
		expectedDate = LocalDate.now();
		formattedDate = expectedDate.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
		given(infoController.getDate(JdbcInfoDao.DATE_INFO.claim_load_date.name())).willReturn(expectedDate);
		given(infoController.getDate(JdbcInfoDao.DATE_INFO.oaf_load_date.name())).willReturn(expectedDate);
		given(infoController.getDate(JdbcInfoDao.DATE_INFO.odf_load_date.name())).willReturn(expectedDate);
		given(infoController.getDate(JdbcInfoDao.DATE_INFO.inference_date.name())).willReturn(expectedDate);
		given(infoController.getDate(JdbcInfoDao.DATE_INFO.stats_update_date.name())).willReturn(expectedDate);
		given(infoController.listInfo()).willReturn(Maps.newHashMap(JdbcInfoDao.DATE_INFO.inference_date.name(), LocalDate.now()));
		given(infoController.listInfoKeys())
			.willReturn(Arrays.stream(JdbcInfoDao.DATE_INFO.values()).map(JdbcInfoDao.DATE_INFO::name).collect(Collectors.toList()));

	}

	@Test
	public void testGetClaimDate() throws Exception {
		mvc.perform(get("/info/claim_load_date")
			.contentType(APPLICATION_JSON_UTF8))
			.andExpect(status().isOk())
			.andExpect(jsonPath("$", is(formattedDate)));
	}

	@Test
	public void testGetOafLoadDate() throws Exception {
		mvc.perform(get("/info/oaf_load_date")
			.contentType(APPLICATION_JSON_UTF8))
			.andExpect(status().isOk())
			.andExpect(jsonPath("$", is(formattedDate)));
	}

	@Test
	public void testGetOdfLoadDate() throws Exception {
		mvc.perform(get("/info/odf_load_date")
			.contentType(APPLICATION_JSON_UTF8))
			.andExpect(status().isOk())
			.andExpect(jsonPath("$", is(formattedDate)));
	}

	@Test
	public void testGetInferenceDate() throws Exception {
		mvc.perform(get("/info/inference_date")
			.contentType(APPLICATION_JSON_UTF8))
			.andExpect(status().isOk())
			.andExpect(jsonPath("$", is(formattedDate)));
	}

	@Test
	public void testGetStatsUpdateDateDate() throws Exception {
		mvc.perform(get("/info/stats_update_date")
			.contentType(APPLICATION_JSON_UTF8))
			.andExpect(status().isOk())
			.andExpect(jsonPath("$", is(formattedDate)));
	}

	@Test
	public void testListAllDates() throws Exception {
		System.out.println(mvc.perform(get("/info")
			.contentType(APPLICATION_JSON_UTF8))
			.andExpect(status().isOk())
			.andReturn()
			.getResponse()
			.getContentAsString());

	}

	@Test
	public void listKeys() throws Exception {
		System.out.println(mvc.perform(get("/info/keys")
			.contentType(APPLICATION_JSON_UTF8))
			.andExpect(status().isOk())
			.andReturn()
			.getResponse()
			.getContentAsString());
	}

}
