using Newtonsoft.Json;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
using UnityEngine;
using UnityEngine.Networking;

namespace Adplay.HTTP
{

    public static class Http
    {
        public static async Task<HttpResponse<T>> Get<T>(string endPoint, Dictionary<string, string> headers)
        {
            UnityWebRequest request = UnityWebRequest.Get(endPoint);
            foreach (var header in headers)
            {
                request.SetRequestHeader(header.Key, header.Value);
            }

            await request.SendWebRequest();
            return new HttpResponse<T>(request.downloadHandler.text, (int)request.responseCode);
        }

        public static async Task<HttpResponse<T>> Get<T>(string endPoint, Dictionary<string, string> headers, Dictionary<string, object> querryParams)
        {
            string urlAndQuerry = BuildEndPointWithQuery(endPoint, querryParams);
            return await Get<T>(urlAndQuerry, headers);
        }


        public static async Task<HttpResponse<Texture2D>> GetTexture<T>(string endPoint, Dictionary<string, string> headers)
        {
            UnityWebRequest request = UnityWebRequestTexture.GetTexture(endPoint);
            foreach (var header in headers)
            {
                request.SetRequestHeader(header.Key, header.Value);
            }

            await request.SendWebRequest();
            Texture2D texture = DownloadHandlerTexture.GetContent(request);

            return new HttpResponse<Texture2D>(texture, (int)request.responseCode);
        }

        public static async Task<HttpResponse<Texture2D>> GetTexture<T>(string endPoint)
        {
            UnityWebRequest request = UnityWebRequestTexture.GetTexture(endPoint);
            await request.SendWebRequest();
            if (request.result != UnityWebRequest.Result.Success)
                return new HttpResponse<Texture2D>(string.Empty, (int)request.responseCode);

            Texture2D texture = DownloadHandlerTexture.GetContent(request);
            return new HttpResponse<Texture2D>(texture, (int)request.responseCode);
        }

        public static async Task<HttpResponse<AudioClip>> GetAudio(string endPoint, AudioType audioType)
        {
            UnityWebRequest request = UnityWebRequestMultimedia.GetAudioClip(endPoint, audioType);
            await request.SendWebRequest();

            if (request.result != UnityWebRequest.Result.Success)
                return new HttpResponse<AudioClip>(string.Empty, (int)request.responseCode);

            AudioClip audioClip = DownloadHandlerAudioClip.GetContent(request);

            return new HttpResponse<AudioClip>(audioClip, (int)request.responseCode);
        }

        public static async Task<HttpResponse<T>> Post<T>(string endPoint, Dictionary<string, string> headers, string jsonData)
        {
            UnityWebRequest request = new(endPoint, "POST");
            byte[] bodyRaw = Encoding.UTF8.GetBytes(jsonData);

            request.uploadHandler = new UploadHandlerRaw(bodyRaw);
            request.downloadHandler = new DownloadHandlerBuffer();
            foreach (var header in headers)
            {
                request.SetRequestHeader(header.Key, header.Value);
            }
            request.certificateHandler = new BypassCertificate();

            await request.SendWebRequest();
            return new HttpResponse<T>(request.downloadHandler.text, (int)request.responseCode);
        }

        public static async Task<HttpResponse<TResult>> Post<TResult, TJson>(string endPoint, Dictionary<string, string> headers, TJson jsonData)
        {
            UnityWebRequest request = new(endPoint, "POST");
            string json = JsonConvert.SerializeObject(jsonData);
            byte[] bodyRaw = Encoding.UTF8.GetBytes(json);
            request.certificateHandler = new BypassCertificate();
            request.uploadHandler = new UploadHandlerRaw(bodyRaw);
            request.downloadHandler = new DownloadHandlerBuffer();
            foreach (var header in headers)
            {
                request.SetRequestHeader(header.Key, header.Value);
            }

            await request.SendWebRequest();

            return new HttpResponse<TResult>(request.downloadHandler.text, (int)request.responseCode);
        }


        private static string BuildEndPointWithQuery(string baseUrl, Dictionary<string, object> queryParams)
        {
            if (queryParams == null || queryParams.Count == 0)
                return baseUrl;

            StringBuilder sb = new StringBuilder();
            sb.Append(baseUrl);
            sb.Append("?");

            foreach (var param in queryParams)
            {
                sb.Append(UnityWebRequest.EscapeURL(param.Key));
                sb.Append("=");
                sb.Append(UnityWebRequest.EscapeURL(param.Value.ToString()));
                sb.Append("&");
            }

            sb.Length--; // remove last "&"
            return sb.ToString();
        }
    }
}
