using Microsoft.EntityFrameworkCore;
using PromotionService.Domain.AggregatesModel.CampaignAggregate;
using PromotionService.Domain.SeedWork;

namespace PromotionService.Infrastructure.Repositories;

/// <summary>
/// EN: Repository implementation for Campaign aggregate.
/// VI: Triển khai repository cho Campaign aggregate.
/// </summary>
public class CampaignRepository : ICampaignRepository
{
    private readonly PromotionServiceContext _context;

    public IUnitOfWork UnitOfWork => _context;

    public CampaignRepository(PromotionServiceContext context)
    {
        _context = context ?? throw new ArgumentNullException(nameof(context));
    }

    public async Task<Campaign?> GetByIdAsync(Guid id)
    {
        return await _context.Campaigns
            .Include(c => c.Vouchers)
            .FirstOrDefaultAsync(c => c.Id == id);
    }

    public async Task<IEnumerable<Campaign>> GetByMerchantIdAsync(Guid merchantId)
    {
        return await _context.Campaigns
            .Where(c => c.MerchantId == merchantId)
            .OrderByDescending(c => c.CreatedAt)
            .ToListAsync();
    }

    public async Task<IEnumerable<Campaign>> GetActiveAsync()
    {
        var now = DateTime.UtcNow;
        return await _context.Campaigns
            .Where(c => c.StatusId == CampaignStatus.Active.Id
                && c.StartDate <= now
                && c.EndDate >= now)
            .OrderBy(c => c.EndDate)
            .ToListAsync();
    }

    public async Task<Voucher?> GetVoucherByCodeAsync(string code)
    {
        return await _context.Vouchers
            .FirstOrDefaultAsync(v => v.Code == code);
    }

    public async Task<IEnumerable<Voucher>> GetUserVouchersAsync(Guid userId)
    {
        return await _context.Vouchers
            .Where(v => v.OwnerId == userId)
            .OrderByDescending(v => v.ClaimedAt)
            .ToListAsync();
    }

    public async Task<Voucher?> GetVoucherByIdAsync(Guid voucherId)
    {
        return await _context.Vouchers
            .FirstOrDefaultAsync(v => v.Id == voucherId);
    }

    public Campaign Add(Campaign campaign)
    {
        return _context.Campaigns.Add(campaign).Entity;
    }

    public void Update(Campaign campaign)
    {
        _context.Entry(campaign).State = EntityState.Modified;
    }
}
