using AdsTrackingService.Domain.SeedWork;

namespace AdsTrackingService.Domain.AggregatesModel.AttributionAggregate;

/// <summary>
/// EN: Attribution window value object - defines time windows for attribution.
/// VI: Value object cửa sổ attribution - định nghĩa khoảng thời gian cho attribution.
/// </summary>
public class AttributionWindow : ValueObject
{
    /// <summary>
    /// EN: Number of days after click to attribute conversion.
    /// VI: Số ngày sau click để gán công conversion.
    /// </summary>
    public int ClickWindowDays { get; private set; }

    /// <summary>
    /// EN: Number of days after view/impression to attribute conversion.
    /// VI: Số ngày sau view/impression để gán công conversion.
    /// </summary>
    public int ViewWindowDays { get; private set; }

    protected AttributionWindow() { }

    public AttributionWindow(int clickWindowDays, int viewWindowDays)
    {
        if (clickWindowDays < 0)
            throw new ArgumentException("Click window days cannot be negative", nameof(clickWindowDays));
        if (viewWindowDays < 0)
            throw new ArgumentException("View window days cannot be negative", nameof(viewWindowDays));
        if (clickWindowDays == 0 && viewWindowDays == 0)
            throw new ArgumentException("Both windows cannot be zero");

        ClickWindowDays = clickWindowDays;
        ViewWindowDays = viewWindowDays;
    }

    // EN: Predefined standard attribution windows
    // VI: Các cửa sổ attribution tiêu chuẩn được định nghĩa sẵn

    /// <summary>
    /// EN: 7-day click attribution window (no view attribution).
    /// VI: Cửa sổ attribution 7 ngày sau click (không tính view).
    /// </summary>
    public static AttributionWindow SevenDayClick => new(7, 0);

    /// <summary>
    /// EN: 1-day view attribution window (no click attribution).
    /// VI: Cửa sổ attribution 1 ngày sau view (không tính click).
    /// </summary>
    public static AttributionWindow OneDayView => new(0, 1);

    /// <summary>
    /// EN: 7-day click + 1-day view attribution window (default).
    /// VI: Cửa sổ attribution 7 ngày click + 1 ngày view (mặc định).
    /// </summary>
    public static AttributionWindow SevenOne => new(7, 1);

    /// <summary>
    /// EN: 28-day click + 1-day view attribution window.
    /// VI: Cửa sổ attribution 28 ngày click + 1 ngày view.
    /// </summary>
    public static AttributionWindow TwentyEightOne => new(28, 1);

    /// <summary>
    /// EN: Check if a conversion is within the attribution window.
    /// VI: Kiểm tra conversion có nằm trong cửa sổ attribution không.
    /// </summary>
    public bool IsWithinWindow(DateTime eventTime, DateTime conversionTime, bool isClick)
    {
        var daysDifference = (conversionTime - eventTime).Days;
        var windowDays = isClick ? ClickWindowDays : ViewWindowDays;
        
        return daysDifference >= 0 && daysDifference <= windowDays;
    }

    protected override IEnumerable<object> GetEqualityComponents()
    {
        yield return ClickWindowDays;
        yield return ViewWindowDays;
    }

    public override string ToString() => $"{ClickWindowDays}d click / {ViewWindowDays}d view";
}
