using DataSharing.Province;
using DataSharing.Share.Dtos.FwDataExchange;
using Microsoft.Extensions.DependencyInjection;
using XF.Domain.Cache;
using XF.Domain.Dependency;
using XF.Domain.Exceptions;

namespace DataSharing.FwDataExchange
{
    public class FwClient : ISingletonDependency, ISelfDependency
    {
        private static readonly string KeyToken = "KeyFwToken";
        private readonly IServiceScopeFactory _scopeFactory;
        //private readonly ISharingConfigurationManager _sharingConfigurationManager;

        /// <summary>
        /// 
        /// </summary>
        /// <param name="scopeFactory"></param>
        public FwClient(IServiceScopeFactory scopeFactory)
        {
            _scopeFactory = scopeFactory;
            // _sharingConfigurationManager = sharingConfigurationManager;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="TResponse"></typeparam>
        /// <param name="url"></param>
        /// <param name="httpMethod"></param>
        /// <param name="stringContent"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<TResponse?> RequestAsync<TResponse>(string url, string httpMethod, string? stringContent = null, CancellationToken cancellationToken = default)
        {
            using var scope = _scopeFactory.CreateScope();
            var provider = scope.ServiceProvider;
            var sharingConfigurationManager = provider.GetRequiredService<ISharingConfigurationManager>();
            var httpInvoker = provider.GetRequiredService<IHttpInvoker>();
            var cacheToken = provider.GetRequiredService<ITypedCache<FwTokenInfo>>();

            var token = cacheToken.GetOrSet(KeyToken,
                   d => GetToken(cancellationToken).GetAwaiter().GetResult(),
                   TimeSpan.FromMinutes(10));
            // var configSendDataOld = sharingConfigurationManager.GetYiBinConfig().SendDataOld.AddressUrl;
            string configSendDataOld = "";
            if (sharingConfigurationManager.IsCity(ConfigurationConsts.YiBin))
                configSendDataOld = sharingConfigurationManager.GetYiBinConfig().SendDataOld.AddressUrl;
            else if (sharingConfigurationManager.IsCity(ConfigurationConsts.ZiGong))
                configSendDataOld = sharingConfigurationManager.GetZiGongConfig().SendDataOld.AddressUrl;
            else if (sharingConfigurationManager.IsCity(ConfigurationConsts.LuZhou))
                configSendDataOld = sharingConfigurationManager.GetLuZhouConfig().SendDataOld.AddressUrl;

            return await httpInvoker.RequestStringContentAsync<TResponse>(url, httpMethod, stringContent,
                d => d.SetHttpClient(configSendDataOld, token?.Token ?? string.Empty), cancellationToken);
        }

        /// <summary>
        /// 获取附件Token
        /// </summary>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<FwTokenInfo> GetFileToken(CancellationToken cancellationToken)
        {
            using var scope = _scopeFactory.CreateScope();
            var provider = scope.ServiceProvider;
            var cacheToken = provider.GetRequiredService<ITypedCache<FwTokenInfo>>();

            var token = cacheToken.GetOrSet(KeyToken,
                   d => GetToken(cancellationToken).GetAwaiter().GetResult(),
                   TimeSpan.FromMinutes(598));

            return token;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<FwTokenInfo> GetToken(CancellationToken cancellationToken)
        {
            using var scope = _scopeFactory.CreateScope();
            var provider = scope.ServiceProvider;
            var cacheToken = provider.GetRequiredService<ITypedCache<FwTokenInfo>>();
            var httpInvoker = provider.GetRequiredService<IHttpInvoker>();

            var sharingConfigurationManager = provider.GetRequiredService<ISharingConfigurationManager>();
            //var configSendDataOld = sharingConfigurationManager.GetYiBinConfig().SendDataOld;
            ConfigurationSendDataOld configSendDataOld = new();
            if (sharingConfigurationManager.IsCity(ConfigurationConsts.YiBin))
                configSendDataOld = sharingConfigurationManager.GetYiBinConfig().SendDataOld;
            else if (sharingConfigurationManager.IsCity(ConfigurationConsts.ZiGong))
                configSendDataOld = sharingConfigurationManager.GetZiGongConfig().SendDataOld;
            else if (sharingConfigurationManager.IsCity(ConfigurationConsts.LuZhou))
                configSendDataOld = sharingConfigurationManager.GetLuZhouConfig().SendDataOld;

            string url = $"api/token?ClientID={configSendDataOld.ClientID}&Secret={configSendDataOld.Secret}";

            var baseAddress = configSendDataOld.AddressUrl;
            if (!baseAddress.EndsWith('/'))
                baseAddress += "/";

            var toke = await httpInvoker.RequestStringContentAsync<FwToken>(baseAddress + url, "Get",
                    null, d => d.SetHttpClient(configSendDataOld.AddressUrl), cancellationToken);

            if (toke is null || toke.data is null)
                throw new UserFriendlyException("获取token请求失败");
            var dataToken = toke.data;
            if (dataToken is null || string.IsNullOrEmpty(dataToken.Token))
                throw new UserFriendlyException("获取token请求失败");

            return dataToken;
        }

        /// <summary>
        /// 请求，不带token
        /// </summary>
        /// <typeparam name="TResponse"></typeparam>
        /// <param name="url"></param>
        /// <param name="httpMethod"></param>
        /// <param name="stringContent"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<TResponse?> RequestNoTokenAsync<TResponse>(string url, string httpMethod, string? stringContent = null, CancellationToken cancellationToken = default)
        {
            using var scope = _scopeFactory.CreateScope();
            var provider = scope.ServiceProvider;
            var channelconfigManager = provider.GetRequiredService<IChannelConfigurationManager>();
            var httpInvoker = provider.GetRequiredService<IHttpInvoker>();

            var configHotlineClient = channelconfigManager.GetConfigurationHotlineClient();
            var postUrl = configHotlineClient.AddressUrl + url;
            return await httpInvoker.RequestStringContentAsync<TResponse>(postUrl, httpMethod, stringContent,
                d => d.SetHttpClient(configHotlineClient.AddressUrl), cancellationToken);
        }

        /// <summary>
        /// 请求，不带token
        /// </summary>
        /// <typeparam name="TResponse"></typeparam>
        /// <param name="addressUrl"></param>
        /// <param name="url"></param>
        /// <param name="httpMethod"></param>
        /// <param name="stringContent"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<TResponse?> RequestNoTokenOtherAsync<TResponse>(string addressUrl,string url, string httpMethod, string? stringContent = null, CancellationToken cancellationToken = default)
        {
            using var scope = _scopeFactory.CreateScope();
            var provider = scope.ServiceProvider;
            var channelconfigManager = provider.GetRequiredService<IChannelConfigurationManager>();
            var httpInvoker = provider.GetRequiredService<IHttpInvoker>();

            return await httpInvoker.RequestStringContentAsync<TResponse>(addressUrl+url, httpMethod, stringContent,
                d => d.SetHttpClient(addressUrl), cancellationToken);
        }

    }
}
