using System;
using System.Collections.Generic;
namespace QRRapidoApp.Models.Ads
{
///
/// Represents the content for a single affiliate advertisement.
///
public class AffiliateAdContent
{
public string Title { get; set; } = string.Empty;
public string? Description { get; set; }
public string ProductUrl { get; set; } = string.Empty;
public string? ImageUrl { get; set; }
public string? CtaText { get; set; }
public string? BadgeText { get; set; }
public string? PriceText { get; set; }
public string? Category { get; set; }
public bool IsEmpty()
{
return string.IsNullOrWhiteSpace(ProductUrl);
}
public AffiliateAdContent Clone()
{
return new AffiliateAdContent
{
Title = Title,
Description = Description,
ProductUrl = ProductUrl,
ImageUrl = ImageUrl,
CtaText = CtaText,
BadgeText = BadgeText,
PriceText = PriceText,
Category = Category
};
}
}
///
/// Configuration for an ad slot, supporting AdSense or affiliate content.
///
public class AdSlotConfiguration
{
///
/// Provider type for the slot. Supported values: "AdSense", "Affiliate".
/// Defaults to "AdSense" to preserve current behaviour.
///
public string Provider { get; set; } = "AdSense";
///
/// Optional custom AdSense slot ID override.
///
public string? AdSenseSlotId { get; set; }
///
/// Affiliate content that will be rendered when is "Affiliate".
///
public AffiliateAdContent? Affiliate { get; set; }
public AdSlotConfiguration Clone()
{
return new AdSlotConfiguration
{
Provider = Provider,
AdSenseSlotId = AdSenseSlotId,
Affiliate = Affiliate?.Clone()
};
}
}
///
/// Root options object bound from configuration for ad slots.
///
public class AdsConfigurationOptions
{
private IDictionary _slots = new Dictionary(StringComparer.OrdinalIgnoreCase);
private IDictionary> _locales = new Dictionary>(StringComparer.OrdinalIgnoreCase);
public IDictionary Slots
{
get => _slots;
set => _slots = CreateSlotDictionary(value);
}
public IDictionary> Locales
{
get => _locales;
set
{
_locales = new Dictionary>(StringComparer.OrdinalIgnoreCase);
if (value == null)
{
return;
}
foreach (var locale in value)
{
_locales[locale.Key] = CreateSlotDictionary(locale.Value);
}
}
}
public AdSlotConfiguration GetSlot(string slotKey, string? cultureName = null)
{
if (string.IsNullOrWhiteSpace(slotKey))
{
slotKey = "header";
}
var localeSlot = TryGetLocaleSlot(slotKey, cultureName);
if (localeSlot != null)
{
return localeSlot.Clone();
}
if (_slots.TryGetValue(slotKey, out var config))
{
return config.Clone();
}
// Default to AdSense when not configured
return new AdSlotConfiguration();
}
private AdSlotConfiguration? TryGetLocaleSlot(string slotKey, string? cultureName)
{
if (string.IsNullOrWhiteSpace(cultureName) || _locales.Count == 0)
{
return null;
}
if (_locales.TryGetValue(cultureName, out var localeSlots) && localeSlots.TryGetValue(slotKey, out var slot))
{
return slot;
}
var neutralCulture = cultureName.Split('-')[0];
if (!string.Equals(neutralCulture, cultureName, StringComparison.OrdinalIgnoreCase)
&& _locales.TryGetValue(neutralCulture, out var neutralSlots)
&& neutralSlots.TryGetValue(slotKey, out var neutralSlot))
{
return neutralSlot;
}
return null;
}
private static IDictionary CreateSlotDictionary(IDictionary? source)
{
var dictionary = new Dictionary(StringComparer.OrdinalIgnoreCase);
if (source == null)
{
return dictionary;
}
foreach (var kvp in source)
{
if (kvp.Value != null)
{
dictionary[kvp.Key] = kvp.Value;
}
}
return dictionary;
}
}
///
/// View model used by the affiliate ad partial.
///
public class AffiliateAdViewModel
{
public string SlotKey { get; set; } = "header";
public string ContainerCssClass { get; set; } = string.Empty;
public AffiliateAdContent Content { get; set; } = new AffiliateAdContent();
}
}