#nullable enable
using System;
using System.Threading.Tasks;
using IGP.UnitySDK.Models;
using Newtonsoft.Json;

namespace IGP.UnitySDK.GameKit
{
    public sealed class IGPProfileException : Exception
    {
        public IGPProfileException(
            string code,
            string message,
            string? upstreamJson = null)
            : base(message)
        {
            Code = code ?? string.Empty;
            UpstreamJson = upstreamJson;
        }

        public string Code { get; }
        public string? UpstreamJson { get; }
    }

    public static class IGPProfile
    {
        public const string InvalidResponseCode = "PROFILE_INVALID_RESPONSE";

        /// <summary>
        /// Fetches the current signed-in user's complete profile through desktop session.
        /// </summary>
        public static async Task<IGPUserProfile> GetProfileAsync(
            IGPRuntimeManager runtimeManager)
        {
            if (runtimeManager == null)
            {
                throw new ArgumentNullException(nameof(runtimeManager));
            }

            IGPDesktopSessionCommandResult result;
            try
            {
                result = await runtimeManager.GetDesktopUserProfileAsync();
            }
            catch (IGPSDKException ex)
            {
                throw new IGPProfileException(
                    string.IsNullOrWhiteSpace(ex.ErrorCode)
                        ? IGPErrorCodes.ERR_DESKTOP_SESSION_REQUIRED
                        : ex.ErrorCode!,
                    string.IsNullOrWhiteSpace(ex.Message)
                        ? "Profile command failed"
                        : ex.Message);
            }

            if (result == null)
            {
                throw new IGPProfileException(
                    IGPErrorCodes.ERR_DESKTOP_SESSION_REQUIRED,
                    "Desktop session returned no profile command result");
            }

            if (!result.Success)
            {
                throw new IGPProfileException(
                    string.IsNullOrWhiteSpace(result.Code)
                        ? IGPErrorCodes.ERR_DESKTOP_SESSION_REQUIRED
                        : result.Code,
                    string.IsNullOrWhiteSpace(result.Message)
                        ? "Profile command failed"
                        : result.Message,
                    result.ContentJson);
            }

            if (string.IsNullOrWhiteSpace(result.ContentJson))
            {
                throw new IGPProfileException(
                    InvalidResponseCode,
                    "Profile response contentJson is empty");
            }

            try
            {
                var profile = JsonConvert.DeserializeObject<IGPUserProfile>(result.ContentJson);
                if (profile == null)
                {
                    throw new IGPProfileException(
                        InvalidResponseCode,
                        "Profile response contentJson could not be parsed",
                        result.ContentJson);
                }

                return profile;
            }
            catch (IGPProfileException)
            {
                throw;
            }
            catch (JsonException ex)
            {
                throw new IGPProfileException(
                    InvalidResponseCode,
                    $"Profile response contentJson is invalid JSON: {ex.Message}",
                    result.ContentJson);
            }
        }
    }
}
