package it.enea.cruise.service.idp;

import java.util.ArrayList;
import java.util.List;

import javax.annotation.PostConstruct;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Profile;
import org.springframework.stereotype.Service;

import it.enea.scp.idp.sdk.business.IdpManager;
import it.enea.scp.idp.sdk.model.ChangePasswordRequest;
import it.enea.scp.idp.sdk.model.ClientDto;
import it.enea.scp.idp.sdk.model.DeleteUserRequest;
import it.enea.scp.idp.sdk.model.IdpResponse;
import it.enea.scp.idp.sdk.model.LoginRequest;
import it.enea.scp.idp.sdk.model.LoginResponse;
import it.enea.scp.idp.sdk.model.TokenValidityResponse;
import it.enea.scp.idp.sdk.model.UpdateUserRequest;
import it.enea.scp.idp.sdk.model.UserDto;
import it.enea.cruise.model.user.User;
import it.enea.cruise.model.user.UserToken;
import lombok.extern.log4j.Log4j2;

@Log4j2
@Service
@Profile("prod")
public class EneaProvider implements IdpProvider {

	@Autowired
	IdpClient ic;

	@Value("${idp.clientId}")
	private String idpClientId;
	
	@Value("${idp.clientSecret}")
	private String idpClientSecret;
	
	//@Value("${idp.clientName}")
	//private String idpClientName;

	//@Value("${idp.id}")
	//private String idClient;

	@Value("${idp.clientSecret}")
	private String clientSecret;
	
	@Value("${idp.login-callback.url}")
	private String idLoginCallbackUrl;
	
	@Value("${idp.logout-callback.url}")
	private String idLogoutCallbackUrl;
	
	@Value("${idp.profile-callback.url}")
	private String idProfileCallbackUrl;
	
	ClientDto clientdto = new ClientDto();

	@PostConstruct
	public void init() {
		clientdto.setClientId(idpClientId);
		clientdto.setClientSecret(idpClientSecret);
		clientdto.setId(1L);
		clientdto.setProfileCallbackUrl(idProfileCallbackUrl);
		clientdto.setLoginCallbackUrl(idLoginCallbackUrl);
		clientdto.setLogoutCallbackUrl(idLogoutCallbackUrl);
	}

	public String getTokenFromUsernameAndPassword(String username, String password) {

		IdpManager idpm = ic.getIdpManagerLocal();

		LoginRequest lRequest = new LoginRequest(username, password);
		IdpResponse<LoginResponse> lResponse = idpm.login(lRequest);

		String token = lResponse.getPayload().getToken().getValue();
		
		return token;
	}
	
	public User login(String username, String password) {
		UserDto user = null;
		User result = new User();
		IdpManager idpm = ic.getIdpManagerLocal();

		LoginRequest lRequest = new LoginRequest(username, password);
		IdpResponse<LoginResponse> lResponse = idpm.login(lRequest);

		if (lResponse.getCode().contains("11")) {
			result = null;
		}else {
			user = lResponse.getPayload().getUser();
			
			result.mergeWithDto(user);
			UserToken userToken = new UserToken();
			userToken.setValue(lResponse.getPayload().getToken().getValue());
			userToken.setCreation(lResponse.getPayload().getToken().getCreation());
			userToken.setExpiration(lResponse.getPayload().getToken().getExpiration());
			
			result.setToken(userToken);
			
		}
		return result;
	}
	
	public boolean logout(String token) {

		IdpManager idpm = ic.getIdpManagerLocal();
		
		IdpResponse<LoginResponse> lResponse = idpm.logout(token);

		boolean logout = lResponse.getPayload().getToken().getValue().length() >0 
				? true : false;
		
		return logout;
	}

	public boolean isValid(String token) {

		IdpManager idpm = ic.getIdpManagerLocal();

		IdpResponse<TokenValidityResponse> lResponse = idpm.isValid(token);

		Boolean isValid = lResponse.getPayload().isValid();

		return isValid;
	}

	public List<UserDto> userList() {

		IdpManager idpm = ic.getIdpManagerLocal();

		IdpResponse<List<UserDto>> lResponse = idpm.userList();

		return lResponse.getPayload();
	}

	public Boolean deleteUser(String email) {

		IdpManager idpm = ic.getIdpManagerLocal();

		DeleteUserRequest dur = new DeleteUserRequest();
		dur.setEmail(email);

		IdpResponse<Boolean> lResponse = idpm.deleteUser(dur);
		
		if(!lResponse.getCode().equals("00")) {
			log.info("Error on getting the user: " + lResponse.getMessage());
			return false;
		}
		
		return lResponse.getPayload();
	}

	public Boolean createUser(UserDto newUser) {

		IdpManager idpm = ic.getIdpManagerLocal();

		List<ClientDto> listClient = new ArrayList<ClientDto>();

		listClient.add(clientdto);
		newUser.setClients(listClient);

		IdpResponse<Boolean> lResponse = idpm.createUser(newUser);
		if(!lResponse.getCode().equals("00")) {
			log.info("Error on getting the user: " + lResponse.getMessage());
			return false;
		}
		return lResponse.getPayload();
	}
	
	public UserDto getUserByEmail(String email) {

		IdpManager idpm = ic.getIdpManagerLocal();

		IdpResponse<UserDto> lResponse = idpm.getUser(email);
		if(!lResponse.getCode().equals("00"))  {
			log.info("Error on getting the user: " + lResponse.getMessage());
		}
		return lResponse.getPayload();
	}
	
	public User getUserByToken(String token) {
		IdpManager idpm = ic.getIdpManagerLocal();
		IdpResponse<TokenValidityResponse> lResponse = idpm.isValid(token);
		User result = new User();
		result.mergeWithDto(lResponse.getPayload().getUser());
		UserToken userToken = new UserToken();
		userToken.setValue(token);
		result.setToken(userToken);
		return result;
	}
	
	
	public Boolean updateUser(UserDto user) {

		IdpManager idpm = ic.getIdpManagerLocal();

		UpdateUserRequest uur = new UpdateUserRequest();
		uur.setUser(user);
		
		IdpResponse<Boolean> lResponse = idpm.updateUser(uur);

		return lResponse.getPayload();
	}
	
	public Boolean updatePassword(String token, String password) {

		IdpManager idpm = ic.getIdpManagerLocal();
		User udto = getUserByToken(token);
		
		ChangePasswordRequest cpr = new ChangePasswordRequest();
		cpr.setEmail(udto.getEmail());
		cpr.setPassword(password);
		cpr.setPasswordConfirm(password);
			
		IdpResponse<Boolean> lResponse = idpm.changePassword(cpr);

		return lResponse.getPayload();
	}
	
	public UserDto getUserFromUUID(String uuid) {

		IdpManager idpm = ic.getIdpManagerLocal();

		IdpResponse<UserDto> lResponse = idpm.getUser(uuid);
		
		if(!lResponse.getCode().equals("00"))  {
			log.info("Error on getting the user: " + lResponse.getMessage());
		}
		return lResponse.getPayload();
	}

}
