using Hotline.Share.Dtos.Snapshot;
using Hotline.Share.Tools;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using Renci.SshNet;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;

namespace TianQue.Sdk;
public class TQHttpClient
{
    private readonly string AppSecret;
    private readonly string AppKey;
    private readonly IHttpClientFactory _httpClientFactory;

    /// <summary>
    /// ssh服务器ip
    /// </summary>
    private readonly string SSHHost;

    /// <summary>
    /// ssh服务器端口
    /// </summary>
    private readonly int SSHPort;

    /// <summary>
    /// ssh账号
    /// </summary>
    private readonly string SSHUserName;

    /// <summary>
    /// ssh密码
    /// </summary>
    private readonly string SSHPassword;

    private readonly SshClient _sshClient;

    private readonly ILogger<TQHttpClient> _logger;

    public TQHttpClient(string appSecret, string appKey, IHttpClientFactory httpClientFactory, ILogger<TQHttpClient> logger)
    {
        AppSecret = appSecret;
        AppKey = appKey;
        _httpClientFactory = httpClientFactory;
        _logger = logger;
    }

    public TQHttpClient(string appSecret, string appKey, string sshHost, int sshPort, string sshUserName, string sshPassword, IHttpClientFactory httpClientFactory, ILogger<TQHttpClient> logger)
        : this(appSecret, appKey, httpClientFactory, logger)
    {
        SSHHost = sshHost;
        SSHPort = sshPort;
        SSHUserName = sshUserName;
        SSHPassword = sshPassword;
        _sshClient = new SshClient(SSHHost, SSHPort, SSHUserName, SSHPassword);
    }

    public async Task<T> PostAsync<T>(Uri uri, object data)
    {
        try
        {
            var headers = new Dictionary<string, object> { { "_timeStamp", DateTime.Now.ToUnixTimeMilliseconds() }, { "_nonce", SignUtils.GenerateNonce() } };
            var sortedDic = new SortedDictionary<string, object>(data.ToDictionary());
            var body = sortedDic.ToJson(new JsonSerializerSettings
            {
                NullValueHandling = NullValueHandling.Ignore,
                ContractResolver = new CamelCasePropertyNamesContractResolver(),
                DateFormatString = "yyyy-MM-dd HH:mm:ss.fff"
            });
            var postJsonSign = SignUtils.Sign(AppSecret, headers, body);
            headers.Add("_sign", postJsonSign);
            headers.Add("_appKey", AppKey);

            if (SSHHost.NotNullOrEmpty() && SSHPort != 0 && SSHUserName.NotNullOrEmpty() && SSHPassword.NotNullOrEmpty())
            {
                var port = new Random().Next(8089, 8099);
                _sshClient.Connect();
                var forwardedPort = new ForwardedPortLocal("127.0.0.1", (uint)port, uri.Host, (uint)uri.Port);
                _sshClient.AddForwardedPort(forwardedPort);
                forwardedPort.Start();
                uri = new Uri("http://127.0.0.1:" + port + uri.AbsolutePath);
            }

            var content = new StringContent(body, Encoding.GetEncoding("UTF-8"));
            content.Headers.ContentType = new MediaTypeHeaderValue("application/json") { CharSet = "UTF-8" };
            foreach (var header in headers)
            {
                content.Headers.Add(header.Key, header.Value.ToString());
            }
            var resp = await (_httpClientFactory.CreateClient()).PostAsync(uri.ToString(), content);
            resp.EnsureSuccessStatusCode();
            var result = await resp.Content.ReadAsStringAsync();
            _logger.LogInformation($"天阙交互; url: {uri.ToString()}, headers: {headers.ToJson()} request: {body}, response: {result}");
            return result.FromJson<T>();
        }
        catch (Exception e)
        {
            _logger.LogError(e.Message);
            throw;
        }
        finally
        {
            if (_sshClient != null && _sshClient.IsConnected)
            {
                _sshClient.Disconnect();
            }
        }
    }
}
