using EonaCat.Json;
using EonaCat.LogStack.Core;
using System;
using System.Net.Http;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace EonaCat.LogStack.Flows
{
    // This file is part of the EonaCat project(s) which is released under the Apache License.
    // See the LICENSE file or go to https://EonaCat.com/License for full license details.

    public class WebhookFlow : FlowBase
    {
        private readonly string _webhookUrl;
        private readonly HttpClient _httpClient;
        private readonly int _maxRetries;
        private readonly TimeSpan _retryDelay;

        public WebhookFlow(string webhookUrl, LogLevel minimumLevel = LogLevel.Trace, int maxRetries = 3, TimeSpan? retryDelay = null) : base($"Webhook:{webhookUrl}", minimumLevel)
        {
            _webhookUrl = webhookUrl ?? throw new ArgumentNullException(nameof(webhookUrl));
            _httpClient = new HttpClient();
            _maxRetries = maxRetries;
            _retryDelay = retryDelay ?? TimeSpan.FromSeconds(1);
        }

        public override async Task<WriteResult> BlastAsync(LogEvent logEvent, CancellationToken cancellationToken = default)
        {
            if (!IsEnabled || !IsLogLevelEnabled(logEvent))
            {
                return WriteResult.LevelFiltered;
            }

            var logPayload = new
            {
                Timestamp = LogEvent.GetDateTime(logEvent.Timestamp),
                Level = logEvent.Level.ToString(),
                Message = logEvent.Message,
                Category = logEvent.Category,
                LogEvent = logEvent
            };

            var jsonPayload = JsonHelper.ToJson(logPayload);
            var content = new StringContent(jsonPayload, Encoding.UTF8, "application/json");

            int attempt = 0;
            while (attempt < _maxRetries)
            {
                try
                {
                    var response = await _httpClient.PostAsync(_webhookUrl, content, cancellationToken);

                    if (response.IsSuccessStatusCode)
                    {
                        return WriteResult.Success;
                    }

                    attempt++;
                    await Task.Delay(_retryDelay, cancellationToken);
                }
                catch (Exception ex)
                {
                    Console.Error.WriteLine($"WebhookFlow error: {ex.Message}");
                    attempt++;
                    await Task.Delay(_retryDelay, cancellationToken);
                }
            }

            return WriteResult.Dropped;
        }

        public override async ValueTask DisposeAsync()
        {
            _httpClient.Dispose();
            await base.DisposeAsync();
        }

        public override Task FlushAsync(CancellationToken cancellationToken = default)
        {
            return Task.CompletedTask;
        }
    }
}
