using System;
using System.IO;
using System.Net.Http;
using System.Text;
using Microsoft.Extensions.Logging;
using StellaOps.Feedser.Source.Common.Fetch;
using StellaOps.Feedser.Source.Vndr.Cisco.Configuration;

namespace StellaOps.Feedser.Source.Vndr.Cisco.Internal;

public interface ICiscoCsafClient
{
    Task<string?> TryFetchAsync(string? url, CancellationToken cancellationToken);
}

public class CiscoCsafClient : ICiscoCsafClient
{
    private static readonly string[] AcceptHeaders = { "application/json", "application/csaf+json", "application/vnd.cisco.csaf+json" };

    private readonly SourceFetchService _fetchService;
    private readonly ILogger<CiscoCsafClient> _logger;

    public CiscoCsafClient(SourceFetchService fetchService, ILogger<CiscoCsafClient> logger)
    {
        _fetchService = fetchService ?? throw new ArgumentNullException(nameof(fetchService));
        _logger = logger ?? throw new ArgumentNullException(nameof(logger));
    }

    public virtual async Task<string?> TryFetchAsync(string? url, CancellationToken cancellationToken)
    {
        if (string.IsNullOrWhiteSpace(url))
        {
            return null;
        }

        if (!Uri.TryCreate(url, UriKind.Absolute, out var uri))
        {
            _logger.LogWarning("Cisco CSAF URL '{Url}' is not a valid absolute URI.", url);
            return null;
        }

        try
        {
            var request = new SourceFetchRequest(CiscoOptions.HttpClientName, VndrCiscoConnectorPlugin.SourceName, uri)
            {
                AcceptHeaders = AcceptHeaders,
            };

            var result = await _fetchService.FetchContentAsync(request, cancellationToken).ConfigureAwait(false);
            if (!result.IsSuccess || result.Content is null)
            {
                _logger.LogWarning("Cisco CSAF download returned status {Status} for {Url}", result.StatusCode, url);
                return null;
            }

            return System.Text.Encoding.UTF8.GetString(result.Content);
        }
        catch (Exception ex) when (ex is HttpRequestException or TaskCanceledException or IOException or InvalidOperationException)
        {
            _logger.LogWarning(ex, "Cisco CSAF download failed for {Url}", url);
            return null;
        }
    }
}
