namespace AdsServingService.API.Application.Events;

/// <summary>
/// EN: Event payload for served-ad event.
/// VI: Payload event cho sự kiện quảng cáo đã được phục vụ.
/// </summary>
public record AdServedEvent
{
    public Guid AuctionId { get; init; }
    public Guid AdId { get; init; }
    public Guid CampaignId { get; init; }
    public Guid UserId { get; init; }
    public string PlacementType { get; init; } = string.Empty;
    public decimal FinalPrice { get; init; }
    public decimal WinningEcpm { get; init; }
    public DateTime ServedAt { get; init; }
}

/// <summary>
/// EN: Event payload for impression.
/// VI: Payload event cho impression.
/// </summary>
public record AdImpressionTrackedEvent
{
    public Guid AdId { get; init; }
    public Guid UserId { get; init; }
    public DateTime Timestamp { get; init; }
}

/// <summary>
/// EN: Event payload for click.
/// VI: Payload event cho click.
/// </summary>
public record AdClickTrackedEvent
{
    public Guid AdId { get; init; }
    public Guid UserId { get; init; }
    public DateTime Timestamp { get; init; }
}

/// <summary>
/// EN: Abstraction for publishing ads-serving events asynchronously.
/// VI: Abstraction để publish bất đồng bộ các sự kiện ads-serving.
/// </summary>
public interface IAdServingEventPublisher
{
    Task PublishAdServedAsync(AdServedEvent payload, CancellationToken cancellationToken);
    Task PublishImpressionTrackedAsync(AdImpressionTrackedEvent payload, CancellationToken cancellationToken);
    Task PublishClickTrackedAsync(AdClickTrackedEvent payload, CancellationToken cancellationToken);
}

/// <summary>
/// EN: Logging-based publisher used as default implementation.
/// VI: Publisher dựa trên logging dùng làm implementation mặc định.
/// </summary>
public class LoggingAdServingEventPublisher : IAdServingEventPublisher
{
    private readonly ILogger<LoggingAdServingEventPublisher> _logger;

    public LoggingAdServingEventPublisher(ILogger<LoggingAdServingEventPublisher> logger)
    {
        _logger = logger ?? throw new ArgumentNullException(nameof(logger));
    }

    public Task PublishAdServedAsync(AdServedEvent payload, CancellationToken cancellationToken)
    {
        _logger.LogInformation(
            "ad.served.v1 event published: AuctionId={AuctionId}, AdId={AdId}, CampaignId={CampaignId}, UserId={UserId}, PlacementType={PlacementType}, FinalPrice={FinalPrice}, WinningEcpm={WinningEcpm}, ServedAt={ServedAt}",
            payload.AuctionId,
            payload.AdId,
            payload.CampaignId,
            payload.UserId,
            payload.PlacementType,
            payload.FinalPrice,
            payload.WinningEcpm,
            payload.ServedAt);

        return Task.CompletedTask;
    }

    public Task PublishImpressionTrackedAsync(AdImpressionTrackedEvent payload, CancellationToken cancellationToken)
    {
        _logger.LogInformation(
            "ads.impression.tracked.v1 event published: AdId={AdId}, UserId={UserId}, Timestamp={Timestamp}",
            payload.AdId,
            payload.UserId,
            payload.Timestamp);

        return Task.CompletedTask;
    }

    public Task PublishClickTrackedAsync(AdClickTrackedEvent payload, CancellationToken cancellationToken)
    {
        _logger.LogInformation(
            "ads.click.tracked.v1 event published: AdId={AdId}, UserId={UserId}, Timestamp={Timestamp}",
            payload.AdId,
            payload.UserId,
            payload.Timestamp);

        return Task.CompletedTask;
    }
}
