using DFS.Infrastructure.Extension.SM;
using Edge.Core.Core.database;
using Microsoft.Extensions.DependencyInjection;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;

namespace Edge.Core.HttpClient
{
    public class HttpClientService:IHttpClient
    {
        private static NLog.Logger Logger = NLog.LogManager.GetCurrentClassLogger();
        private readonly string signMethod = "HMAC_SM4";
        private string acesskey = "";
        private string secretId = "";
        private string buildId = "";
        private string baseUrl = "";
        private readonly MysqlDbContext mysqlDbContext = new MysqlDbContext();

        private IHttpClientFactory _httpContextFactory;

        [ActivatorUtilitiesConstructor]
        public HttpClientService(IHttpClientFactory httpClientFactory) 
        {
            _httpContextFactory = httpClientFactory;
            getHttpInfo();
        }

        private void getHttpInfo()
        {
            var fccStationInfo = mysqlDbContext.FccStationInfos.FirstOrDefault();
            if(fccStationInfo ==  null)
            {
                Logger.Info($"http client get station info fail");
                return;
            }
            secretId = fccStationInfo?.SecretId;
            buildId = fccStationInfo?.BuildId;
            acesskey = fccStationInfo?.AcessKey;
            baseUrl = fccStationInfo?.CloudService;
        }

        public async Task<HttpResponseMessage> GetAsync(string api, Dictionary<string,string> parmas)
        {
            System.Net.Http.HttpClient httpClient = await GetHttpClient(null,parmas);
            return await httpClient.GetAsync(api);
        }

        public async Task<HttpResponseMessage> PostAsync(string api, StringContent? parmaJson)
        {
            System.Net.Http.HttpClient httpClient = await GetHttpClient(parmaJson, null);
            return await httpClient.PostAsync(api, parmaJson);
        }

        public async Task<HttpResponseMessage> PutAsync(string api, StringContent? parmaJson)
        {
            System.Net.Http.HttpClient httpClient = await GetHttpClient(parmaJson, null);
            return await httpClient.PutAsync(api, parmaJson);
        }

        public async Task<HttpResponseMessage> DeleteAsync(string api, StringContent? parmaJson)
        {
            System.Net.Http.HttpClient httpClient = await GetHttpClient(parmaJson, null);
            HttpRequestMessage httpRequestMessage = new HttpRequestMessage(HttpMethod.Delete, api);
            httpRequestMessage.Content = parmaJson;
            return await httpClient.SendAsync(httpRequestMessage);
        }


        private async Task<System.Net.Http.HttpClient> GetHttpClient(StringContent? parmaJson, Dictionary<string, string>? parmas)
        {
            string nonceStr = GenerateUniqueString();
            string timeStampStr = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds().ToString();

            var httpClient = _httpContextFactory.CreateClient();
            httpClient.BaseAddress = new Uri(baseUrl);
            httpClient.DefaultRequestHeaders.Add("sign_method", signMethod);
            httpClient.DefaultRequestHeaders.Add("secret_id", secretId);
            httpClient.DefaultRequestHeaders.Add("nonce", nonceStr);
            httpClient.DefaultRequestHeaders.Add("timestamp", timeStampStr);
            httpClient.DefaultRequestHeaders.Add("CurrentBuId", buildId);
            if (parmaJson != null)
            {
                string json = await parmaJson.ReadAsStringAsync();
                httpClient.DefaultRequestHeaders.Add("signature", SignStr(nonceStr, timeStampStr, json, null));

            }
            else
            {
                httpClient.DefaultRequestHeaders.Add("signature", SignStr(nonceStr, timeStampStr, null, parmas));
            }

            return httpClient;
        }

        private string GenerateUniqueString()
        {
            // 生成 GUID 并去掉 "-"
            string guid = Guid.NewGuid().ToString("N");
            // 截取前 7 位
            return guid.Substring(0, 7);
        }

        private string SignStr(string nonce,string timestamp, string? parmaJson,Dictionary<string,string>? parmas)
        {
            string sign = $"sign_method={signMethod}&secret_id={secretId}&nonce={nonce}&timestamp={timestamp}";
            if(parmaJson != null)
            {
                sign += $"&{parmaJson}";
            }
            if (parmas != null)
            {
                foreach (var item in parmas)
                {
                    sign += $"&{item.Key}={item.Value}";
                }
            }
            
            string encrySign = sign.SM4Encrypt_ECB(acesskey);
            byte[] encrySignBytes = Encoding.UTF8.GetBytes(encrySign);
            string encryBase64 = Convert.ToBase64String(encrySignBytes);
            return encryBase64;
        }
    }
}
