using Microsoft.Extensions.Logging;
using System.Text;

namespace Leanetec.EConnect.Infrastructure;

public static class LogExtensions
{
    public static async Task LogCurlAsync<TCategoryName>(
        this ILogger<TCategoryName> logger,
        HttpClient client,
        HttpMethod? method = null,
        string? route = null,
        HttpContent? content = null,
        HttpRequestMessage? requestMessage = null,
        LogLevel logLevel = LogLevel.Information)
    {
        route ??= requestMessage?.RequestUri?.ToString();

        var sb = new StringBuilder();
        sb.Append("curl");

        // Method
        sb.Append($" -X {method?.Method ?? requestMessage?.Method.ToString()}");

        // URL
        var fullUrl = string.Empty;
        if (client.BaseAddress is not null && route is not null)
            fullUrl = new Uri(client.BaseAddress, route).ToString();
        else if (route is not null)
            fullUrl = route;
        else if (client.BaseAddress is not null)
            fullUrl = client.BaseAddress.ToString();

        if (!string.IsNullOrWhiteSpace(fullUrl))
            sb.AppendLine($" \"{fullUrl}\"");

        // Headers
        foreach (var header in client.DefaultRequestHeaders)
        {
            sb.AppendLine($"\t-H \"{header.Key}: {string.Join(", ", header.Value)}\"");
        }

        // Headers
        if (requestMessage is not null)
            foreach (var header in requestMessage.Headers)
            {
                sb.AppendLine($"\t-H \"{header.Key}: {string.Join(", ", header.Value)}\"");
            }

        if (content != null)
        {
            foreach (var header in content.Headers)
            {
                sb.AppendLine($"\t-H \"{header.Key}: {string.Join(", ", header.Value)}\"");
            }

            var mediaType = content.Headers.ContentType?.MediaType;
            if (mediaType is not null && mediaType.StartsWith("text") || mediaType!.Contains("json"))
            {
                var body = await content.ReadAsStringAsync();
                if (!string.IsNullOrWhiteSpace(body))
                {
                    // Escape double quotes
                    body = body.Replace("\"", "\\\"");
                    sb.AppendLine($"\t-d \"{body}\"");
                }
            }
            else
                // Binary content, only placeholder in log
                sb.AppendLine("\t-d \"<binary data>\"");
        }
        
        logger.Log(logLevel, "{message}", sb.ToString());
    }
}