using Microsoft.EntityFrameworkCore;
using AdsTrackingService.Domain.AggregatesModel.ConversionAggregate;
using AdsTrackingService.Domain.SeedWork;

namespace AdsTrackingService.Infrastructure.Repositories;

/// <summary>
/// EN: Repository implementation for Conversion aggregate.
/// VI: Triển khai repository cho aggregate Conversion.
/// </summary>
public class ConversionRepository : IConversionRepository
{
    private readonly AdsTrackingServiceContext _context;

    public IUnitOfWork UnitOfWork => _context;

    public ConversionRepository(AdsTrackingServiceContext context)
    {
        _context = context ?? throw new ArgumentNullException(nameof(context));
    }

    public async Task<IEnumerable<Conversion>> GetByCampaignIdAsync(
        Guid campaignId, 
        int skip, 
        int take, 
        CancellationToken ct = default)
    {
        return await _context.Conversions
            .Where(c => c.CampaignId == campaignId)
            .OrderByDescending(c => c.ConversionTime)
            .Skip(skip)
            .Take(take)
            .ToListAsync(ct);
    }

    public async Task<IEnumerable<Conversion>> GetByUserIdAsync(Guid userId, CancellationToken ct = default)
    {
        return await _context.Conversions
            .Where(c => c.UserId == userId)
            .OrderByDescending(c => c.ConversionTime)
            .ToListAsync(ct);
    }

    public async Task<IEnumerable<Conversion>> GetByTimeRangeAsync(
        DateTime from, 
        DateTime to, 
        CancellationToken ct = default)
    {
        return await _context.Conversions
            .Where(c => c.ConversionTime >= from && c.ConversionTime <= to)
            .OrderByDescending(c => c.ConversionTime)
            .ToListAsync(ct);
    }

    public async Task<Conversion?> GetByIdAsync(Guid id, CancellationToken ct = default)
    {
        return await _context.Conversions.FindAsync(new object[] { id }, ct);
    }

    public async Task<Conversion> AddAsync(Conversion entity, CancellationToken ct = default)
    {
        return (await _context.Conversions.AddAsync(entity, ct)).Entity;
    }

    public Conversion Update(Conversion entity)
    {
        return _context.Conversions.Update(entity).Entity;
    }

    public void Delete(Conversion entity)
    {
        _context.Conversions.Remove(entity);
    }
}
