// 
// Decompiled by Procyon v0.6.0
// 

package com.hypixel.hytale.server.core.auth;

import java.util.function.Function;
import com.hypixel.hytale.codec.builder.BuilderCodec;
import com.hypixel.hytale.codec.KeyedCodec;
import com.hypixel.hytale.codec.Codec;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.concurrent.CompletableFuture;
import javax.annotation.Nullable;
import java.io.IOException;
import com.hypixel.hytale.codec.ExtraInfo;
import com.hypixel.hytale.codec.EmptyExtraInfo;
import com.hypixel.hytale.codec.util.RawJsonReader;
import java.net.http.HttpResponse;
import java.net.URI;
import java.net.http.HttpRequest;
import java.util.UUID;
import java.util.logging.Level;
import javax.annotation.Nonnull;
import java.net.http.HttpClient;
import java.time.Duration;
import com.hypixel.hytale.logger.HytaleLogger;

public class ProfileServiceClient
{
    private static final HytaleLogger LOGGER;
    private static final Duration REQUEST_TIMEOUT;
    private final HttpClient httpClient;
    private final String profileServiceUrl;
    
    public ProfileServiceClient(@Nonnull final String profileServiceUrl) {
        if (profileServiceUrl == null || profileServiceUrl.isEmpty()) {
            throw new IllegalArgumentException("Profile Service URL cannot be null or empty");
        }
        this.profileServiceUrl = (profileServiceUrl.endsWith("/") ? profileServiceUrl.substring(0, profileServiceUrl.length() - 1) : profileServiceUrl);
        this.httpClient = HttpClient.newBuilder().connectTimeout(ProfileServiceClient.REQUEST_TIMEOUT).build();
        ProfileServiceClient.LOGGER.at(Level.INFO).log("Profile Service client initialized for: %s", this.profileServiceUrl);
    }
    
    @Nullable
    public PublicGameProfile getProfileByUuid(@Nonnull final UUID uuid, @Nonnull final String bearerToken) {
        try {
            final HttpRequest request = HttpRequest.newBuilder().uri(URI.create(this.profileServiceUrl + "/profile/uuid/" + uuid.toString())).header("Accept", "application/json").header("Authorization", "Bearer " + bearerToken).header("User-Agent", AuthConfig.USER_AGENT).timeout(ProfileServiceClient.REQUEST_TIMEOUT).GET().build();
            ProfileServiceClient.LOGGER.at(Level.FINE).log("Fetching profile by UUID: %s", uuid);
            final HttpResponse<String> response = this.httpClient.send(request, HttpResponse.BodyHandlers.ofString());
            if (response.statusCode() != 200) {
                ProfileServiceClient.LOGGER.at(Level.WARNING).log("Failed to fetch profile by UUID: HTTP %d - %s", response.statusCode(), response.body());
                return null;
            }
            final PublicGameProfile profile = PublicGameProfile.CODEC.decodeJson(new RawJsonReader(response.body().toCharArray()), EmptyExtraInfo.EMPTY);
            if (profile == null) {
                ProfileServiceClient.LOGGER.at(Level.WARNING).log("Profile Service returned invalid response for UUID: %s", uuid);
                return null;
            }
            ProfileServiceClient.LOGGER.at(Level.FINE).log("Successfully fetched profile: %s (%s)", profile.getUsername(), profile.getUuid());
            return profile;
        }
        catch (final IOException e) {
            ProfileServiceClient.LOGGER.at(Level.WARNING).log("IO error while fetching profile by UUID: %s", e.getMessage());
            return null;
        }
        catch (final InterruptedException e2) {
            ProfileServiceClient.LOGGER.at(Level.WARNING).log("Request interrupted while fetching profile by UUID");
            Thread.currentThread().interrupt();
            return null;
        }
        catch (final Exception e3) {
            ProfileServiceClient.LOGGER.at(Level.WARNING).log("Unexpected error fetching profile by UUID: %s", e3.getMessage());
            return null;
        }
    }
    
    public CompletableFuture<PublicGameProfile> getProfileByUuidAsync(@Nonnull final UUID uuid, @Nonnull final String bearerToken) {
        return CompletableFuture.supplyAsync(() -> this.getProfileByUuid(uuid, bearerToken));
    }
    
    @Nullable
    public PublicGameProfile getProfileByUsername(@Nonnull final String username, @Nonnull final String bearerToken) {
        try {
            final String encodedUsername = URLEncoder.encode(username, StandardCharsets.UTF_8);
            final HttpRequest request = HttpRequest.newBuilder().uri(URI.create(this.profileServiceUrl + "/profile/username/" + encodedUsername)).header("Accept", "application/json").header("Authorization", "Bearer " + bearerToken).header("User-Agent", AuthConfig.USER_AGENT).timeout(ProfileServiceClient.REQUEST_TIMEOUT).GET().build();
            ProfileServiceClient.LOGGER.at(Level.FINE).log("Fetching profile by username: %s", username);
            final HttpResponse<String> response = this.httpClient.send(request, HttpResponse.BodyHandlers.ofString());
            if (response.statusCode() != 200) {
                ProfileServiceClient.LOGGER.at(Level.WARNING).log("Failed to fetch profile by username: HTTP %d - %s", response.statusCode(), response.body());
                return null;
            }
            final PublicGameProfile profile = PublicGameProfile.CODEC.decodeJson(new RawJsonReader(response.body().toCharArray()), EmptyExtraInfo.EMPTY);
            if (profile == null) {
                ProfileServiceClient.LOGGER.at(Level.WARNING).log("Profile Service returned invalid response for username: %s", username);
                return null;
            }
            ProfileServiceClient.LOGGER.at(Level.FINE).log("Successfully fetched profile: %s (%s)", profile.getUsername(), profile.getUuid());
            return profile;
        }
        catch (final IOException e) {
            ProfileServiceClient.LOGGER.at(Level.WARNING).log("IO error while fetching profile by username: %s", e.getMessage());
            return null;
        }
        catch (final InterruptedException e2) {
            ProfileServiceClient.LOGGER.at(Level.WARNING).log("Request interrupted while fetching profile by username");
            Thread.currentThread().interrupt();
            return null;
        }
        catch (final Exception e3) {
            ProfileServiceClient.LOGGER.at(Level.WARNING).log("Unexpected error fetching profile by username: %s", e3.getMessage());
            return null;
        }
    }
    
    public CompletableFuture<PublicGameProfile> getProfileByUsernameAsync(@Nonnull final String username, @Nonnull final String bearerToken) {
        return CompletableFuture.supplyAsync(() -> this.getProfileByUsername(username, bearerToken));
    }
    
    private static <T> KeyedCodec<T> externalKey(final String key, final Codec<T> codec) {
        return new KeyedCodec<T>(key, codec, false, true);
    }
    
    static {
        LOGGER = HytaleLogger.forEnclosingClass();
        REQUEST_TIMEOUT = Duration.ofSeconds(5L);
    }
    
    public static class PublicGameProfile
    {
        public static final BuilderCodec<PublicGameProfile> CODEC;
        private UUID uuid;
        private String username;
        
        public PublicGameProfile() {
        }
        
        public PublicGameProfile(final UUID uuid, final String username) {
            this.uuid = uuid;
            this.username = username;
        }
        
        public UUID getUuid() {
            return this.uuid;
        }
        
        public String getUsername() {
            return this.username;
        }
        
        static {
            CODEC = BuilderCodec.builder(PublicGameProfile.class, PublicGameProfile::new).append((KeyedCodec<UUID>)ProfileServiceClient.externalKey("uuid", (Codec<FieldType>)Codec.UUID_STRING), (p, v) -> p.uuid = v, PublicGameProfile::getUuid).add().append(ProfileServiceClient.externalKey("username", (Codec<Object>)Codec.STRING), (p, v) -> p.username = v, PublicGameProfile::getUsername).add().build();
        }
    }
}
