using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Security.Policy;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

/// <summary>
/// http调用帮助类
/// </summary>
public class HttpHelper
{
    /// <summary>
    /// 文件删除模型
    /// </summary>
    class FileDeleteDto
    {
        /// <summary>
        /// 要删除的服务器上的文件名称
        /// </summary>
        public List<string> Files { get; set; }
    }
    /// <summary>
    /// 
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="url"></param>
    /// <param name="dto"></param>
    /// <param name="timeoutSeconds"></param>
    /// <param name="token"></param>
    /// <returns></returns>
    public static async Task<AjaxResult<T>> PostRequestAsync<T>(string url, object dto, int timeoutSeconds = 60, CancellationToken token = default)
    {
        var content = new StringContent(JsonConvert.SerializeObject(dto), System.Text.Encoding.UTF8, "application/json");
        var handler = new HttpClientHandler() { UseCookies = false };
        HttpClient client = new HttpClient(handler);
        client.Timeout = TimeSpan.FromSeconds(timeoutSeconds);
        var message = new HttpRequestMessage(HttpMethod.Post, url);
        message.Content = content;

        var response = await client.SendAsync(message, token);
        response.EnsureSuccessStatusCode();
        var result = await response.Content.ReadAsStringAsync();
        var AjaxResult = JsonConvert.DeserializeObject<AjaxResult<T>>(result);
        return AjaxResult;
    }

    /// <summary>
    /// 
    /// </summary>
    /// <param name="url"></param>
    /// <param name="dto"></param>
    /// <param name="token"></param>
    /// <param name="timeoutSeconds"></param>
    /// <returns></returns>
    public static async Task<AjaxResult> PostRequestAsync(string url, object dto, int timeoutSeconds = 60, CancellationToken token = default)
    {
        var content = new StringContent(JsonConvert.SerializeObject(dto), System.Text.Encoding.UTF8, "application/json");
        var handler = new HttpClientHandler() { UseCookies = false };
        HttpClient client = new HttpClient(handler);
        client.Timeout = TimeSpan.FromSeconds(timeoutSeconds);
        var message = new HttpRequestMessage(HttpMethod.Post, url);
        message.Content = content;

        var response = await client.SendAsync(message, token);
        response.EnsureSuccessStatusCode();
        var result = await response.Content.ReadAsStringAsync();
        var AjaxResult = JsonConvert.DeserializeObject<AjaxResult>(result);
        return AjaxResult;
    }

    public static async Task<AjaxResult<T>> GetRequestAsync<T>(string url, int timeoutSeconds = 60)
    {
        var handler = new HttpClientHandler() { UseCookies = false };
        HttpClient client = new HttpClient(handler);
        client.Timeout = TimeSpan.FromSeconds(timeoutSeconds);
        var response = await client.GetAsync(url);
        response.EnsureSuccessStatusCode();
        var result = await response.Content.ReadAsStringAsync();
        var AjaxResult = JsonConvert.DeserializeObject<AjaxResult<T>>(result);
        return AjaxResult;
    }

    /// <summary>
    /// 
    /// </summary>
    /// <param name="baseUrl"></param>
    /// <param name="remoteFileName"></param>
    /// <param name="localFile"></param>
    /// <param name="timeoutSeconds"></param>
    /// <returns></returns>
    public static async Task<bool> DownloadFileAsync(string baseUrl, string remoteFileName, string localFile, int timeoutSeconds = 30)
    {
        baseUrl = baseUrl.Replace("/api", "");
        if (!baseUrl.EndsWith("/"))
            baseUrl += "/";
        var server = new Uri(baseUrl + $"wwwroot/{remoteFileName}");
        var httpClient = new HttpClient();
        httpClient.Timeout = TimeSpan.FromSeconds(timeoutSeconds);
        var responseMessage = await httpClient.GetAsync(server);
        if (responseMessage.IsSuccessStatusCode)
        {
            using (var fs = File.Create(localFile))
            {
                // 获取结果，并转成 stream 保存到本地。
                var streamFromService = await responseMessage.Content.ReadAsStreamAsync();
                streamFromService.CopyTo(fs);
            }
            return true;
        }
        else
            return false;

    }

    /// <summary>
    /// 上传文件,wav文件会自动去掉44字节头
    /// </summary>
    /// <param name="localFile"></param>
    /// <param name="baseUrl"></param>
    /// <param name="timeoutSeconds"></param>
    /// <param name="token"></param>
    /// <returns></returns>
    public static async Task<string> UploadFileAsync(string localFile, string baseUrl, int timeoutSeconds = 30, CancellationToken token = default)
    {
        string uploadUrl = baseUrl;
        if (baseUrl.EndsWith("/"))
            uploadUrl += "File/UploadFileAsync";
        else
            uploadUrl += "/File/UploadFileAsync";
        try
        {
            // 添加文件内容到 MultipartFormDataContent
            FileInfo info = new FileInfo(localFile);
            bool isWav = info.Extension.ToLower() == ".wav";
            byte[] fileBytes = File.ReadAllBytes(localFile);
            if (isWav)
            {
                fileBytes = fileBytes.Skip(44).ToArray();//wav文件有44字节头
            }
            MultipartFormDataContent content = new MultipartFormDataContent();
            ByteArrayContent fileContent = new ByteArrayContent(fileBytes);
            content.Add(fileContent, "file", Path.GetFileName(localFile));
            var handler = new HttpClientHandler() { UseCookies = false };
            HttpClient client = new HttpClient(handler);
            client.Timeout = TimeSpan.FromSeconds(timeoutSeconds);
            var message = new HttpRequestMessage(HttpMethod.Post, uploadUrl);
            message.Content = content;

            var response = await client.SendAsync(message, token);
            response.EnsureSuccessStatusCode();
            var result = await response.Content.ReadAsStringAsync();
            var AjaxResult = JsonConvert.DeserializeObject<AjaxResult<string>>(result);
            if (AjaxResult.code == 200)
            {
                return AjaxResult.data;
            }
            else
            {
                throw new Exception(AjaxResult.msg);
            }
        }
        catch (TaskCanceledException)
        {
            if (token != null && token.IsCancellationRequested)
                throw new TaskCanceledException();
            else
                throw new Exception($"上传文件{Path.GetFileName(localFile)}到{uploadUrl}超时!");

        }
        catch (Exception ex)
        {
            throw new Exception($"上传文件{Path.GetFileName(localFile)}到{uploadUrl}失败!", ex);
        }
    }


    /// <summary>
    /// 删除文件
    /// </summary>
    /// <param name="files">要删除的文件</param>
    /// <param name="baseUrl">baseUrl</param>
    /// <returns></returns>
    public static async Task<int> DeleteFileAsync(string[] files, string baseUrl)
    {
        FileDeleteDto dto = new FileDeleteDto()
        {
            Files = files.ToList()
        };
        var content = new StringContent(JsonConvert.SerializeObject(dto), System.Text.Encoding.UTF8, "application/json");
        var handler = new HttpClientHandler() { UseCookies = false };
        HttpClient client = new HttpClient(handler);
        client.Timeout = TimeSpan.FromSeconds(30);
        var message = new HttpRequestMessage(HttpMethod.Post, baseUrl + "/File/DeleteFiles");
        message.Content = content;

        var response = await client.SendAsync(message);
        response.EnsureSuccessStatusCode();
        var result = await response.Content.ReadAsStringAsync();
        var AjaxResult = JsonConvert.DeserializeObject<AjaxResult<int>>(result);
        return AjaxResult.data;
    }

    /// <summary>
    /// 删除文件
    /// </summary>
    /// <param name="files">要删除的文件</param>
    /// <param name="baseUrl">baseUrl</param>
    /// <returns></returns>
    public static async Task<int> DeleteFileAsync(string baseUrl, params string[] files)
    {
        FileDeleteDto dto = new FileDeleteDto()
        {
            Files = files.ToList()
        };
        var content = new StringContent(JsonConvert.SerializeObject(dto), System.Text.Encoding.UTF8, "application/json");
        var handler = new HttpClientHandler() { UseCookies = false };
        HttpClient client = new HttpClient(handler);
        client.Timeout = TimeSpan.FromSeconds(30);
        var message = new HttpRequestMessage(HttpMethod.Post, baseUrl + "/File/DeleteFiles");
        message.Content = content;

        var response = await client.SendAsync(message);
        response.EnsureSuccessStatusCode();
        var result = await response.Content.ReadAsStringAsync();
        var AjaxResult = JsonConvert.DeserializeObject<AjaxResult<int>>(result);
        return AjaxResult.data;
    }
}

/// <summary>
/// Http接口返回泛型对象
/// </summary>
public class AjaxResult<T>
{
    /// <summary>
    /// 返回对象
    /// </summary>
    public T data { get; set; }

    /// <summary>
    /// 返回消息
    /// </summary>
    public string msg { get; set; } = "ok";

    /// <summary>
    /// 状态码.成功=200,失败=0
    /// </summary>
    public int code { get; set; } = 200;

}
/// <summary>
/// Http接口返回对象
/// </summary>
public class AjaxResult
{
    /// <summary>
    /// 返回对象
    /// </summary>
    public object data { get; set; }

    /// <summary>
    /// 返回消息
    /// </summary>
    public string msg { get; set; } = "ok";

    /// <summary>
    /// 状态码.成功=200,失败=0
    /// </summary>
    public int code { get; set; } = 200;

}

