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 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;
            acesskey = fccStationInfo?.AcessKey;
            baseUrl = fccStationInfo?.CloudService;
        }

        public async Task<HttpResponseMessage> GetAsync(string api, 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("signature", SignStr(nonceStr,timeStampStr,null,parmas));

            return await httpClient.GetAsync(api);
        }

        public async Task<HttpResponseMessage> PostAsync(string api, StringContent? parmaJson)
        {
            string nonceStr = GenerateUniqueString();
            string timeStampStr = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds().ToString();

            string? json = null;
            if (parmaJson != null)
            {
                json = await parmaJson.ReadAsStringAsync();
            }
            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("signature", SignStr(nonceStr, timeStampStr, json,null));

            return await httpClient.PostAsync(api, parmaJson);
        }

        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;
        }
    }
}