package org.fuseri.confidentialclient;

import org.fuseri.model.dto.user.UserCreateDto;
import org.fuseri.model.dto.user.UserDto;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.security.oauth2.client.OAuth2AuthorizedClient;
import org.springframework.security.oauth2.client.annotation.RegisteredOAuth2AuthorizedClient;
import org.springframework.security.oauth2.core.OAuth2AccessToken;
import org.springframework.security.oauth2.core.oidc.user.OidcUser;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestClientException;
import org.springframework.web.client.RestTemplate;

@RestController
public class AuthClientController {

    @GetMapping("/token")
    public String getToken(@RegisteredOAuth2AuthorizedClient OAuth2AuthorizedClient oauth2Client) {
        return oauth2Client.getAccessToken().getTokenValue();
    }

    @GetMapping("/register")
    public String register(@RegisteredOAuth2AuthorizedClient OAuth2AuthorizedClient oauth2Client, @AuthenticationPrincipal OidcUser user) {
        var createDto = new UserCreateDto();
        createDto.setLastName(user.getFamilyName());
        createDto.setFirstName(user.getGivenName());
        createDto.setEmail(user.getSubject()); // MUNI includes as subject user email
        createDto.setUsername(user.getPreferredUsername());

        // add access token to API call
        OAuth2AccessToken accessToken = oauth2Client.getAccessToken();
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        headers.setBearerAuth(accessToken.getTokenValue());
        HttpEntity<UserCreateDto> request = new HttpEntity<>(createDto, headers);

        String url = buildRegisterUrl();
        RestTemplate userRegisterRestTemplate = new RestTemplate();

        try {
            var response = userRegisterRestTemplate.postForObject(url, request, UserDto.class);
            return response == null ? "Unable to register user." : response.toString();
        } catch (RestClientException e) {
            return "Unable to register user: " + e.getMessage();
        }
    }

    private static String buildRegisterUrl() {
        String host;
        if (!Boolean.parseBoolean(System.getenv("DOCKER_RUNNING")))
            host = "localhost";
        else host = switch (System.getProperty("os.name")) {
            case "mac os x" -> "docker.for.mac.localhost";
            case "windows" -> "host.docker.internal";
            default -> "language-school"; // linux and others
        };
        return "http://" + host + ":8081/users/register";
    }
}
