using System;
using System.Text;
using System.Threading.Tasks;
using UnityEngine;
using UnityEngine.Networking;

namespace Furlumin.SDK.Editor
{
    [Serializable]
    internal sealed class AssetInfo
    {
        public string id;
        public string name;
        public string description;
        public string group;
        public string version;
        public long   sizeBytes;
        public string checksum;
        public string thumbnailUrl;
        public string downloadUrl;
    }

    internal static class FurluminAPIClient
    {
        private const string BaseUrl           = "https://api.furlumin.de";
        private const int    ApiTimeoutSeconds = 15;

        internal static async Task<(bool success, long statusCode, string body, AssetInfo[] assets)> GetAssetsAsync()
        {
            if (!FurluminAuthManager.IsLoggedIn())
                return (false, 401, null, null);

            var (ok, status, body) = await GetAsync("/api/sdk/assets", authorized: true);
            AssetInfo[] assets = null;
            if (ok)
            {
                try   { assets = JsonArrayHelper.FromJsonArray<AssetInfo>(body); }
                catch (Exception e) { Debug.LogError("[Furlumin SDK] Could not parse asset response: " + e.Message); }
            }
            return (ok, status, body, assets);
        }

        internal static async Task<(bool success, long statusCode, string body)> GetAsync(
            string path, bool authorized)
        {
            if (string.IsNullOrEmpty(path) || !path.StartsWith("/"))
            {
                Debug.LogError("[Furlumin SDK] Invalid API path: " + path);
                return (false, 0, null);
            }

            if (authorized && !FurluminAuthManager.IsLoggedIn())
                return (false, 401, null);

            using var req = UnityWebRequest.Get(BaseUrl + path);
            req.timeout   = ApiTimeoutSeconds;
            req.SetRequestHeader("X-SDK-Client", "Furlumin-Unity/1.0");
            if (authorized) ApplyAuth(req);
            await SendAsync(req);
            return (req.result == UnityWebRequest.Result.Success,
                    req.responseCode,
                    req.downloadHandler?.text);
        }

        internal static async Task<(bool success, long statusCode, string body)> PostAsync(
            string path, object payload, bool authorized)
        {
            if (string.IsNullOrEmpty(path) || !path.StartsWith("/"))
            {
                Debug.LogError("[Furlumin SDK] Invalid API path: " + path);
                return (false, 0, null);
            }

            if (authorized && !FurluminAuthManager.IsLoggedIn())
                return (false, 401, null);

            string json          = payload != null ? JsonUtility.ToJson(payload) : "{}";
            using var req        = new UnityWebRequest(BaseUrl + path, "POST");
            byte[] raw           = Encoding.UTF8.GetBytes(json);
            req.uploadHandler    = new UploadHandlerRaw(raw);
            req.downloadHandler  = new DownloadHandlerBuffer();
            req.timeout          = ApiTimeoutSeconds;
            req.SetRequestHeader("Content-Type", "application/json");
            req.SetRequestHeader("X-SDK-Client", "Furlumin-Unity/1.0");
            if (authorized) ApplyAuth(req);
            await SendAsync(req);
            return (req.result == UnityWebRequest.Result.Success,
                    req.responseCode,
                    req.downloadHandler?.text);
        }

        private static void ApplyAuth(UnityWebRequest req)
        {
            string token = FurluminAuthManager.GetToken();
            if (!string.IsNullOrEmpty(token))
                req.SetRequestHeader("Authorization", "Bearer " + token);
        }

        private static Task SendAsync(UnityWebRequest req)
        {
            var tcs = new TaskCompletionSource<bool>();
            req.SendWebRequest().completed += _ => tcs.SetResult(true);
            return tcs.Task;
        }
    }

    internal static class JsonArrayHelper
    {
        [Serializable]
        private sealed class Wrapper<T> { public T[] items; }

        internal static T[] FromJsonArray<T>(string json)
        {
            if (string.IsNullOrWhiteSpace(json)) return new T[0];
            var wrapper = JsonUtility.FromJson<Wrapper<T>>("{\"items\":" + json + "}");
            return wrapper?.items ?? new T[0];
        }
    }
}
