package it.enea.cruise;

import org.junit.jupiter.api.MethodOrderer;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestMethodOrder;
import org.junit.jupiter.api.Order;
import org.junit.runner.RunWith;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.http.MediaType;
import org.springframework.test.context.TestPropertySource;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.MvcResult;
import org.springframework.test.web.servlet.ResultHandler;

import com.fasterxml.jackson.databind.ObjectMapper;

import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.*;

import it.enea.cruise.config.SpringFoxConfig;
import it.enea.cruise.config.dataDBConfiguration;
import it.enea.cruise.config.userDBConfiguration;
import it.enea.cruise.controller.UserController;
import it.enea.cruise.dto.LocalUserDTO;
import it.enea.cruise.service.idp.IEncryptionManager;
import it.enea.cruise.service.idp.IdpProvider;
import it.enea.scp.idp.sdk.model.UserDto;


@RunWith(SpringRunner.class)
@SpringBootTest(classes= {userDBConfiguration.class, SpringFoxConfig.class, dataDBConfiguration.class})
@TestPropertySource(
		locations = "classpath:application.properties")
@AutoConfigureMockMvc
@ComponentScan(basePackages = "it.enea.cruise")
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
class GecoRegistrationSpringApplicationTests {
	//@Value("${t.userToken}")
	//private String userToken;

	//@Value("${t.adminToken}")
	//private String adminToken;

	@Value("${idp.testAdminEmail}")
	String userAdminEmail;

	@Value("${idp.testAdminPwd}")
	String userAdminPwd;

	@Value("${idp.testUserEmail}")
	String testUserEmail;

	@Value("${idp.testUserPwd}")
	String testUserPwd;

	@Autowired
	private MockMvc mvc;

	@Autowired
    IdpProvider idpClientManager;

	@Autowired
	IEncryptionManager encryptionManager;

	@Autowired
	UserController userController;

	private String token;


	@Test
	@Order(5)
	void getUserFromEmailAndPassword() throws Exception {

	mvc.perform(
				post("/user/login")
				.contentType(MediaType.APPLICATION_JSON)
				.param("username", userAdminEmail)
				.param("password", userAdminPwd))
		.andExpect(status().isOk())
		.andDo(print());
		
		mvc.perform(
				post("/user/login")
				.contentType(MediaType.APPLICATION_JSON)
				.param("username", testUserEmail)
				.param("password", testUserPwd))
		.andExpect(status().isOk())
		.andDo(print());

		mvc.perform(
				post("/user/login")
				.contentType(MediaType.APPLICATION_JSON)
				.param("username", testUserEmail + "w")
				.param("password", testUserPwd))
		.andExpect(status().isForbidden())
		.andDo(print());
		
//		String userContent ="{\n"
//				+ "  \"name\": \"Gianluca\",\n"
//				+ "  \"surname\": \"D'Agosta\",\n"
//				+ "  \"organization\": \"EnergyCommunity\",\n"
//				+ "  \"email\": \"gianluca.dagosta@cancellamiAppenaPuoi.it\",\n"
//				+ "  \"password\": \"cancellami!\",\n"
//				+ "  \"userroles\": [\n"
//				+ "    {\n"
//				+ "      \"role\": {\n"
//				+ "        \"roleID\": 2,\n"
//				+ "        \"communityID\": 4,\n"
//				+ "        \"roleName\": \"registered\",\n"
//				+ "        \"description\": \"registered\"\n"
//				+ "      }\n"
//				+ "    }\n"
//				+ "  ],\n"
//				+ "  \"usercommunities\": [\n"
//				+ "    {\n"
//				+ "      \"community\": {\n"
//				+ "        \"communityid\": 4,\n"
//				+ "        \"communityName\": \"Farlock\",\n"
//				+ "        \"description\": \"Comunita' di test\",\n"
//				+ "        \"wallet\": \"dhòljhà jpeoqàjàpjfaàkàhlkanhàlkjàoiteàih\"\n"
//				+ "      }\n"
//				+ "    }\n"
//				+ "  ]\n"
//				+ "}";
//		
//		mvc.perform(
//				post("/user/register")
//				.contentType(MediaType.APPLICATION_JSON)
//				.content(userContent))
//		.andExpect(status().isCreated())
//		.andDo(print());
//		
//		String deleteContent = "gianluca.dagosta@cancellamiAppenaPuoi.it";
//		
//		mvc.perform(
//				delete("/user/delete")
//				.contentType(MediaType.APPLICATION_JSON)
//				.content(deleteContent))
//		.andExpect(status().isOk())
//		.andDo(print());
		
	}

	@Test
	@Order(6)
	void getData() throws Exception {

		Handler handler = new Handler();

		mvc.perform(
				post("/user/login")
				.contentType(MediaType.APPLICATION_JSON)
				.param("username", testUserEmail)
				.param("password", testUserPwd))
		.andExpect(status().isOk())
		.andDo(handler)
		.andDo(print());

		
		mvc.perform(
				post("/user/getUserIdFromToken")
				.contentType(MediaType.APPLICATION_JSON)
				.header("Authorization", token))
		.andExpect(status().isOk())
		.andDo(print());
		
		mvc.perform(
				post("/user/isTokenValid")
				.contentType(MediaType.APPLICATION_JSON)
				.header("Authorization", token))
		.andExpect(status().isOk())
		.andDo(print());
		
		mvc.perform(
				post("/data/getListOfFunctions")
				.contentType(MediaType.APPLICATION_JSON)
				.header("Authorization", token))
		.andExpect(status().isOk())
		.andDo(print());

		String content ="{"
				+ "\"communityid\": 2,\n"
				+ " \"queryid\":2,\n"
				+ "\" endDate\": \"2021-09-22 23:59:59\",\n"
				+ "\" startDate\":\"2021-09-22 00:00:00\"\n"
				+ "}";



		mvc.perform(
				post("/data/getData")
				.contentType(MediaType.APPLICATION_JSON)
				.header("Authorization", token)
				.header("Content-Language", "it_IT")
				.content (content))				
		.andExpect(status().isOk())
		//.andExpect(jsonPath("$.result", greaterThan(2)))
		.andDo(print());

		content ="{\"communityid\": 2,\n"
				+ " \"queryid\":1,\n"
				+ "\" maxValue\": \"3000\",\n"
				+ "\" minValue\":\"0\"\n"
				+ "}";


		mvc.perform(
				post("/data/getData")
				.contentType(MediaType.APPLICATION_JSON)
				.header("Authorization", token)
				.header("Content-Language", "it_IT")
				.content(content))
		.andExpect(status().isOk())
		.andDo(print());

		content ="{\"communityid\": 2,\n"
				+ " \"queryid\":5,\n"
				+ "\" endDate\": \"2021-09-22 23:59:59\",\n"
				+ "\" startDate\":\"2021-09-21 00:00:00\"\n"
				+ "}";

		mvc.perform(
				post("/data/getData")
				.contentType(MediaType.APPLICATION_JSON)
				.header("Authorization", token)
				.header("Content-Language", "it_IT")
				.content(content))
		.andExpect(status().isOk())
		.andDo(print());

		content ="{\"communityid\": 2,\n"
				+ " \"queryid\":2,\n"
				+ "\" endDate\": \"2021-09-22 23:59:59\",\n"
				+ "\" startDate\":\"2021-09-21 00:00:00\"\n"
				+ "}";


		mvc.perform(
				post("/data/getData")
				.contentType(MediaType.APPLICATION_JSON)
				.header("Authorization", token)
				.header("Content-Language", "it_IT")
				.content(content))
		.andExpect(status().isOk())
		.andDo(print());

		content ="{\"communityid\": 2,\n"
				+ " \"queryid\":6\n"
				+ "}";

		mvc.perform(
				post("/data/getData")
				.contentType(MediaType.APPLICATION_JSON)
				.header("Authorization", token)
				.header("Content-Language", "it_IT")
				.content(content))
		.andExpect(status().isOk())
		.andDo(print());

		content ="{\"queryid\":4\n"
				+ "}";

		mvc.perform(
				post("/data/getData")
				.contentType(MediaType.APPLICATION_JSON)
				.header("Authorization", token)
				.content(content))
		.andExpect(status().isOk())
		.andDo(print());

		mvc.perform(
				post("/user/logout")
				.contentType(MediaType.APPLICATION_JSON)
				.header("Authorization", token)
				.param("token", token))
		.andExpect(status().isOk())
		.andDo(print());

	}

	/*
	 * Questo test verifica le funzioni di estrazione dei dati dal DB.
	 * Devono ancora implementare la gestione degli utenti.
	 * 
	 */
	//	@Test
	//	@Order(12)
	//	void getConsumptionData() throws Exception {
	//		mvc.perform(
	//				post("/data/getInstantConsumption"))
	//				.andExpect(status().isOk())
	//				.andDo(print())
	//				.andExpect(jsonPath("$..property").exists())
	//			    .andExpect(jsonPath("$..val").isNotEmpty());
	//		
	//		mvc.perform(
	//				post("/data/todayConsumption"))
	//				.andExpect(status().isOk())
	//				.andDo(print())
	//				.andExpect(jsonPath("$..property").exists())
	//			    .andExpect(jsonPath("$..val").isNotEmpty());	
	//		
	//		mvc.perform(
	//				post("/data/getConsumptionInAPeriod")
	//				.queryParam("startDate", "2021-06-01 00:00:00")
	//				.queryParam("endDate", "2021-06-07  00:00:00")
	//				)
	//				.andExpect(status().isOk())
	//				.andDo(print())
	//				.andExpect(jsonPath("$..property").exists())
	//			    .andExpect(jsonPath("$..val").isNotEmpty());	
	//		
	//		
	//	}


	private class Token  {
		String token;

		public Token(String token) {
			this.token = token;
		}

		public String getToken() {
			return this.token;
		}

		public void setToken (String token) {
			this.token = token;
		}
	}

	private UserDto createFakeUserDto(){

		UserDto user = new UserDto();

		user.setAddress("Via qualsiasi, un po' piu' in la' 32, 00100 Ovunque");
		user.setName("cancellami");
		user.setSurname("D'Agosta");
		user.setPhone("0516098466");
		user.setEmail("utente.ec@test.it");
		user.setEmailConfirmed(true);
		user.setPassword("gianluca.dagosta");
		user.setOrganization("Comunita' GECO");
		user.setPasswordConfirm("gianluca.dagosta");
		user.setRole("Citizen");

		return user;

	}

	private class Handler implements ResultHandler{

		@Override
		public void handle(MvcResult result) throws Exception {
			String pippo = result.getResponse().getContentAsString();
			LocalUserDTO user = new ObjectMapper().readValue(pippo, LocalUserDTO.class);
			token = user.getToken().getValue();
			//System.out.println(result);

		}
	}
}
