using Microsoft.Extensions.Caching.Memory;

namespace OnlyOneAccessTemplate.Services
{
    public class AdsService : IAdsService
    {
        private readonly IConfiguration _configuration;
        private readonly IMemoryCache _cache;
        private readonly ILogger<AdsService> _logger;

        public AdsService(IConfiguration configuration, IMemoryCache cache, ILogger<AdsService> logger)
        {
            _configuration = configuration;
            _cache = cache;
            _logger = logger;
        }

        public bool IsAdsEnabled()
        {
            return _configuration.GetValue<bool>("GoogleAds:Enabled", true);
        }

        public string GetPublisherID()
        {
            return _configuration.GetValue<string>("GoogleAds:PublisherID") ?? "";
        }

        public AdConfiguration GetAdConfiguration(string adPosition)
        {
            var configurations = GetAllAdConfigurations();
            return configurations.FirstOrDefault(c => c.Position.Equals(adPosition, StringComparison.OrdinalIgnoreCase))
                ?? new AdConfiguration(adPosition, "default-slot", AdSize.Responsive);
        }

        public string GenerateAdHtml(string position, string adSlot, AdSize size = AdSize.Responsive)
        {
            if (!IsAdsEnabled() || string.IsNullOrEmpty(GetPublisherID()))
                return "";

            var sizeAttributes = GetSizeAttributes(size);
            var formatAttribute = GetFormatAttribute(size);

            return $@"
                <ins class=""adsbygoogle""
                     style=""display:block{sizeAttributes.Style}""
                     data-ad-client=""{GetPublisherID()}""
                     data-ad-slot=""{adSlot}""
                     {formatAttribute}
                     {(size == AdSize.Responsive ? "data-full-width-responsive=\"true\"" : "")}></ins>";
        }

        private List<AdConfiguration> GetAllAdConfigurations()
        {
            return _cache.GetOrCreate("ad_configurations", factory =>
            {
                factory.SetSlidingExpiration(TimeSpan.FromHours(1));

                return new List<AdConfiguration>
                {
                    new("banner-top", GetSlotId("BannerTop"), AdSize.Banner_728x90, Priority: 10),
                    new("sidebar-left", GetSlotId("SidebarLeft"), AdSize.Sidebar_300x600, IsSticky: true, ShowOnMobile: false, Priority: 8),
                    new("rectangle-pre-converter", GetSlotId("RectanglePre"), AdSize.Rectangle_300x250, Priority: 9),
                    new("rectangle-post-converter", GetSlotId("RectanglePost"), AdSize.Rectangle_300x250, Priority: 7),
                    new("sidebar-right", GetSlotId("SidebarRight"), AdSize.Sidebar_300x600, IsSticky: true, ShowOnMobile: false, Priority: 6),
                    new("mobile-bottom", GetSlotId("MobileBottom"), AdSize.Mobile_320x50, ShowOnDesktop: false, Priority: 5),
                    new("in-feed", GetSlotId("InFeed"), AdSize.Responsive, Priority: 4),
                    new("multiplex", GetSlotId("Multiplex"), AdSize.Responsive, Priority: 3)
                };
            });
        }

        private string GetSlotId(string configKey)
        {
            return _configuration.GetValue<string>($"GoogleAds:Slots:{configKey}") ?? "default-slot";
        }

        private (string Style, string Width, string Height) GetSizeAttributes(AdSize size)
        {
            return size switch
            {
                AdSize.Banner_728x90 => ("; width: 728px; height: 90px;", "728", "90"),
                AdSize.Rectangle_300x250 => ("; width: 300px; height: 250px;", "300", "250"),
                AdSize.Sidebar_160x600 => ("; width: 160px; height: 600px;", "160", "600"),
                AdSize.Sidebar_300x600 => ("; width: 300px; height: 600px;", "300", "600"),
                AdSize.Mobile_320x50 => ("; width: 320px; height: 50px;", "320", "50"),
                AdSize.Square_250x250 => ("; width: 250px; height: 250px;", "250", "250"),
                _ => ("", "auto", "auto")
            };
        }

        private string GetFormatAttribute(AdSize size)
        {
            return size switch
            {
                AdSize.Responsive => "data-ad-format=\"auto\"",
                AdSize.Banner_728x90 => "data-ad-format=\"banner\"",
                AdSize.Rectangle_300x250 => "data-ad-format=\"rectangle\"",
                AdSize.Sidebar_160x600 or AdSize.Sidebar_300x600 => "data-ad-format=\"vertical\"",
                AdSize.Square_250x250 => "data-ad-format=\"square\"",
                _ => "data-ad-format=\"auto\""
            };
        }
    }
}
