using Lentia.Core.Constants;
using System.Text.Json.Serialization;
using System.Net.Http.Json;
using Lentia.Core.Utils;

namespace Lentia.Core.Auth.Yggdrasil;

public record YggdrasilError(
    string error,
    string? cause,
    string errorMessage
);

public record AuthenticateResponse(
    [property: JsonPropertyName("user")] UserRecord User,
    [property: JsonPropertyName("clientToken")] string ClientToken,
    [property: JsonPropertyName("accessToken")] string AccessToken,
    [property: JsonPropertyName("availableProfiles")] List<ProfileRecord> AvailableProfiles,
    [property: JsonPropertyName("selectedProfile")] ProfileRecord SelectedProfile
);

public record UserRecord {
    [JsonPropertyName("username")]
    public string Username { get; set; }

    [JsonPropertyName("properties")]
    public List<UserProperty> Properties { get; init; }

    [JsonPropertyName("id")]
    public string? Id { get; init; }

    public UserRecord(string Username, List<UserProperty> Properties, string? Id) {
        this.Username = Username;
        this.Properties = Properties;
        this.Id = Id;
    }
}

public record UserProperty(
    string Name,
    string Value
);

public record ProfileRecord(
    string Name,
    string Id
);

public class AuthResult {
    public bool Success { get; set; }
    public AuthenticateResponse? Player { get; set; }    
    public YggdrasilError? Error { get; set; }

    public static AuthResult Ok(AuthenticateResponse data) => new() {
        Success = true,
        Player = data,
        Error = null
    };

    public static AuthResult Fail(string message, string? errorType = null, string? cause = null) => new() {
        Success = false,
        Player = null,
        Error = new YggdrasilError(errorType ?? "UnknownError", cause, message)
    };
}

public class Authenticator {
    public async Task<AuthResult> Login(string _username, string _password) {
        var payload = new {
            agent = new {
                name = "Minecraft",
                version = 1        
            },
            username = _username,
            password = _password,
            requestUser = true
        };

        try {
            var response = await HttpHelper.FetchAsync(LauncherConstants.Urls.MojangAuthServer + "/authenticate", HttpMethod.Post, payload);
            if (!response.IsSuccessStatusCode) {
                var errorData = await response.Content.ReadFromJsonAsync<YggdrasilError>();
                return AuthResult.Fail(
                    errorData?.errorMessage ?? "Identifiants invalides.",
                    errorData?.error,
                    errorData?.cause
                );
            }
            
            var data = await response.Content.ReadFromJsonAsync<AuthenticateResponse>();
            return data != null ? AuthResult.Ok(data) : AuthResult.Fail("Erreur de lecture des données.");
        } catch (HttpRequestException ex) {
            return AuthResult.Fail($"Erreur réseau : {ex.Message}", "NETWORK_ERROR");
        } catch (Exception ex) {
            return AuthResult.Fail($"Erreur interne : {ex.Message}", "INTERNAL_ERROR");
        }
    }
}