package eu.eudat.logic.security.customproviders.ConfigurableProvider;

import eu.eudat.logic.security.customproviders.ConfigurableProvider.entities.oauth2.Oauth2ConfigurableProviderUserSettings;
import eu.eudat.logic.security.validators.configurableProvider.helpers.ConfigurableProviderResponseToken;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;

import java.util.Map;

@Component("configurableProviderCustomProvider")
public class ConfigurableProviderCustomProviderImpl implements ConfigurableProviderCustomProvider {

	@Override
	public ConfigurableProviderResponseToken getAccessToken(String code, String redirectUri, String clientId, String clientSecret, String accessTokenUrl,
															String grantType, String access_token, String expires_in) {
		RestTemplate template = new RestTemplate();
		HttpHeaders headers = new HttpHeaders();
		headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);

		MultiValueMap<String, String> map = new LinkedMultiValueMap<String, String>();

		map.add("grant_type", grantType);
		map.add("code", code);
		map.add("redirect_uri", redirectUri);
		map.add("client_id", clientId);
		map.add("client_secret", clientSecret);
		HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<>(map, headers);

		Map<String, Object> values = template.postForObject(accessTokenUrl, request, Map.class);
		ConfigurableProviderResponseToken responseToken = new ConfigurableProviderResponseToken();
		responseToken.setAccessToken((String) values.get(access_token));
		if (expires_in != null && !expires_in.isEmpty()) {
			responseToken.setExpiresIn((Integer) values.get(expires_in));
		}

		return responseToken;
	}

	@Override
	public ConfigurableProviderUser getUser(String accessToken, Oauth2ConfigurableProviderUserSettings user) {
		RestTemplate restTemplate = new RestTemplate();
		HttpHeaders headers = this.createBearerAuthHeaders(accessToken);
		HttpEntity<String> entity = new HttpEntity<>(headers);

		Map<String, Object> values = restTemplate.exchange(user.getUser_info_url(), HttpMethod.GET, entity, Map.class).getBody();
		return new ConfigurableProviderUser().getConfigurableProviderUser(values, user);
	}

	private HttpHeaders createBearerAuthHeaders(String accessToken) {
		return new HttpHeaders() {{
			String authHeader = "Bearer " + accessToken;
			set("Authorization", authHeader);
		}};
	}
}
