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

import com.fasterxml.jackson.databind.ObjectMapper;
import eu.eudat.logic.security.validators.orcid.helpers.ORCIDResponseToken;
import eu.eudat.logic.security.validators.zenodo.helpers.ZenodoResponseToken;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
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.HttpClientErrorException;
import org.springframework.web.client.RestTemplate;

import java.io.IOException;
import java.util.Collections;
import java.util.Map;

@Component("ZenodoCustomProvider")
public class ZenodoCustomProviderImpl implements ZenodoCustomProvider {
    private static final Logger logger = LoggerFactory.getLogger(ZenodoCustomProviderImpl.class);

    private Environment environment;

    @Autowired
    public ZenodoCustomProviderImpl(Environment environment) {
        this.environment = environment;
    }

    @Override
    public ZenodoResponseToken getAccessToken(ZenodoAccessType accessType, String code, String clientId, String clientSecret, String redirectUri) {
        RestTemplate restTemplate = new RestTemplate();
        HttpHeaders headers = new HttpHeaders();
        headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));
        headers.setContentType(MediaType.MULTIPART_FORM_DATA);

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

        try {
            Map<String, Object> values = restTemplate.postForObject(this.environment.getProperty("zenodo.login.access_token_url"), request, Map.class);
            ZenodoResponseToken zenodoResponseToken = new ZenodoResponseToken();
            Map<String, Object> user = (Map<String, Object>) values.get("user");
            zenodoResponseToken.setUserId((String) user.get("id"));
            zenodoResponseToken.setEmail((String) user.get("email"));
            zenodoResponseToken.setExpiresIn((Integer) values.get("expires_in"));
            zenodoResponseToken.setAccessToken((String) values.get("access_token"));
            zenodoResponseToken.setRefreshToken((String) values.get("refresh_token"));

            return zenodoResponseToken;
        } catch (HttpClientErrorException ex) {
            logger.error(ex.getResponseBodyAsString(), ex);
        }

        return null;
    }

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