using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Net;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;

namespace EVCB_OCPP.WSServer.Service
{
    public class OuterHttpClient
    {
        private HttpClientService httpClient = new HttpClientService();

        async public Task<HttpResult> Post(string url, Dictionary<string, string> headers, object requestBody, string saltkey)
        {
            HttpResult result = new HttpResult() { Success = false };

            try
            {
                string body = PreAction(url, ref headers, requestBody, saltkey);
                var _response = await httpClient.PostJsonAsync(url, body, headers);

                result.Response = _response.Response;
                result.Status = _response.StatusCode;
                result.Success = _response.IsSuccessStatusCode;
                result.Exception = _response.Exception;


            }
            catch (Exception ex)
            {
                result.Exception = ex;
            }

            return result;
        }


        async public Task<HttpResult> PostFormDataAsync(string url, Dictionary<string, string> bodyData, Dictionary<string, string> headers, string clientName = "Default", bool bearerToken = false, string authorizationToken = null)
        {
            HttpResult result = new HttpResult() { Success = false };

            try
            {

                var _response = await httpClient.PostFormDataAsync(url, bodyData, null);

                result.Response = _response.Response;
                result.Status = _response.StatusCode;
                result.Success = _response.IsSuccessStatusCode;
                result.Exception = _response.Exception;


            }
            catch (Exception ex)
            {
                result.Exception = ex;
            }

            return result;
        }

        async public Task<HttpResult> GetWeather(string url, Dictionary<string, string> headers, string saltkey)
        {

            HttpResult result = new HttpResult() { Success = false };

            try
            {
               // string body = PreAction(url, ref headers, null, saltkey);
                var _response = await httpClient.GetJsonAsync(url, headers);
                result.Response = _response.Response;
                result.Status = _response.StatusCode;
                result.Success = _response.IsSuccessStatusCode;
                result.Exception = _response.Exception;



            }
            catch (Exception ex)
            {
                result.Exception = ex;
            }

            return result;
        }



        async public Task<HttpResult> Get(string url, Dictionary<string, string> headers, string saltkey)
        {

            HttpResult result = new HttpResult() { Success = false };

            try
            {
                string body = PreAction(url, ref headers, null, saltkey);
                var _response = await httpClient.GetJsonAsync(url, headers);
                result.Response = _response.Response;
                result.Status = _response.StatusCode;
                result.Success = _response.IsSuccessStatusCode;
                result.Exception = _response.Exception;



            }
            catch (Exception ex)
            {
                result.Exception = ex;
            }

            return result;
        }

        async public Task<HttpResult> Delete(string url, Dictionary<string, string> headers, string saltkey)
        {
            HttpResult result = new HttpResult() { Success = false };

            try
            {
                string body = PreAction(url, ref headers, null, saltkey);
                var _response = await httpClient.DeleteJsonAsync(url, headers);
                result.Response = _response.Response;
                result.Status = _response.StatusCode;
                result.Success = _response.IsSuccessStatusCode;
                result.Exception = _response.Exception;


            }
            catch (Exception ex)
            {
                result.Exception = ex;
            }

            return result;
        }

        async public Task<HttpResult> Put(string url, Dictionary<string, string> headers, object requestBody, string saltkey)
        {
            HttpResult result = new HttpResult() { Success = false };

            try
            {
                string body = PreAction(url, ref headers, requestBody, saltkey);
                var _response = await httpClient.PutJsonAsync(url, body, headers);
                result.Response = _response.Response;
                result.Status = _response.StatusCode;
                result.Success = _response.IsSuccessStatusCode;
                result.Exception = _response.Exception;


            }
            catch (Exception ex)
            {
                result.Exception = ex;
            }

            return result;
        }

        private string PreAction(string url, ref Dictionary<string, string> headers, object requestBody, string saltkey)
        {
            var _body = requestBody == null ? "" : JsonConvert.SerializeObject(requestBody, GlobalConfig.JSONSERIALIZER_FORMAT);
            headers.Add("Timestamp", DateTimeOffset.UtcNow.ToUnixTimeSeconds().ToString());
            string signature = GetSignature(GetUnencodeText(url, _body, headers["Timestamp"], headers["PartnerId"], saltkey));
            headers.Add("Signature", signature);

            return _body;
        }


        private string GetUnencodeText(string url, string body, string timestamp, string partnerId, string saltkey)
        {

            string tempText = url.Substring(url.IndexOf('?') + 1).ToLower();
            tempText = tempText.StartsWith("http") ? string.Empty : tempText;
            body = tempText + body;
            string unencodeText = string.Format("{0}{1}{2}{3}", body, timestamp, partnerId, saltkey).ToLower();

            return unencodeText;
        }

        private string GetSignature(string unencodeText)
        {
            if ((unencodeText == null) || (unencodeText.Length == 0))
            {
                return String.Empty;
            }
            unencodeText = unencodeText.ToLower();

            MD5 md5 = new MD5CryptoServiceProvider();
            byte[] textToHash = Encoding.UTF8.GetBytes(unencodeText);
            byte[] result = md5.ComputeHash(textToHash);
            return BitConverter.ToString(result).Replace("-", "").ToLower();
        }

    }

    public class HttpResult
    {
        public int StatusCode { set; get; }

        public bool Success { set; get; }

        public HttpStatusCode Status { set; get; }

        public Exception Exception { set; get; }

        public string Response { set; get; }

    }

}
