using Ganss.Xss;
using Microsoft.Extensions.Options;
using NexusReader.Application.Abstractions.Services;
using NexusReader.Infrastructure.Configuration;
using Markdig;

namespace NexusReader.Infrastructure.Services;

/// <summary>
/// Infrastructure implementation of ISanitizerService using the Ganss.Xss HtmlSanitizer library.
/// </summary>
public class HtmlSanitizerService : ISanitizerService
{
    private readonly HtmlSanitizer _sanitizer;
    private readonly MarkdownPipeline _pipeline;

    public HtmlSanitizerService(IOptions<HtmlSanitizerSettings>? options = null)
    {
        _sanitizer = new HtmlSanitizer();
        _pipeline = new MarkdownPipelineBuilder().UseAdvancedExtensions().Build();
        
        if (options?.Value != null)
        {
            var settings = options.Value;
            
            if (settings.AllowedTags != null && settings.AllowedTags.Count > 0)
            {
                _sanitizer.AllowedTags.Clear();
                foreach (var tag in settings.AllowedTags)
                {
                    _sanitizer.AllowedTags.Add(tag);
                }
            }

            if (settings.AllowedAttributes != null && settings.AllowedAttributes.Count > 0)
            {
                _sanitizer.AllowedAttributes.Clear();
                foreach (var attr in settings.AllowedAttributes)
                {
                    _sanitizer.AllowedAttributes.Add(attr);
                }
            }

            if (settings.AllowedCssProperties != null && settings.AllowedCssProperties.Count > 0)
            {
                _sanitizer.AllowedCssProperties.Clear();
                foreach (var prop in settings.AllowedCssProperties)
                {
                    _sanitizer.AllowedCssProperties.Add(prop);
                }
            }

            if (settings.AllowedSchemes != null && settings.AllowedSchemes.Count > 0)
            {
                _sanitizer.AllowedSchemes.Clear();
                foreach (var scheme in settings.AllowedSchemes)
                {
                    _sanitizer.AllowedSchemes.Add(scheme);
                }
            }
        }
    }

    public string Sanitize(string input)
    {
        if (string.IsNullOrEmpty(input))
        {
            return input;
        }

        // Translate raw Markdown input to HTML strictly before running HtmlSanitizer
        var html = Markdown.ToHtml(input, _pipeline);

        return _sanitizer.Sanitize(html).Trim();
    }
}
