namespace WalletService.Infrastructure.Repositories;

using Microsoft.EntityFrameworkCore;
using WalletService.Domain.AggregatesModel.WalletAggregate;
using WalletService.Domain.SeedWork;

/// <summary>
/// EN: Repository implementation for Wallet aggregate
/// VI: Repository implementation cho aggregate Wallet
/// </summary>
public class WalletRepository : IWalletRepository
{
    private readonly WalletServiceContext _context;

    public IUnitOfWork UnitOfWork => _context;

    public WalletRepository(WalletServiceContext context)
    {
        _context = context ?? throw new ArgumentNullException(nameof(context));
    }

    public async Task<Wallet?> GetByIdAsync(Guid walletId)
    {
        return await _context.Wallets
            .Include(w => w.Balances)
            .FirstOrDefaultAsync(w => w.Id == walletId);
    }

    public async Task<Wallet?> GetByUserIdAsync(Guid userId)
    {
        return await _context.Wallets
            .Include(w => w.Balances)
            .FirstOrDefaultAsync(w => w.UserId == userId);
    }

    public async Task<Wallet?> GetByIdWithTransactionsAsync(Guid walletId)
    {
        return await _context.Wallets
            .Include(w => w.Transactions)
            .FirstOrDefaultAsync(w => w.Id == walletId);
    }

    public async Task<IEnumerable<WalletTransaction>> GetTransactionsAsync(
        Guid walletId,
        int page = 1,
        int pageSize = 20)
    {
        return await _context.WalletTransactions
            .Where(t => t.WalletId == walletId)
            .OrderByDescending(t => t.CreatedAt)
            .Skip((page - 1) * pageSize)
            .Take(pageSize)
            .ToListAsync();
    }

    public async Task<int> CountTransactionsAsync(Guid walletId)
    {
        return await _context.WalletTransactions
            .CountAsync(t => t.WalletId == walletId);
    }

    public async Task<bool> ExistsByUserIdAsync(Guid userId)
    {
        return await _context.Wallets
            .AnyAsync(w => w.UserId == userId);
    }

    public Wallet Add(Wallet wallet)
    {
        return _context.Wallets.Add(wallet).Entity;
    }

    public void Update(Wallet wallet)
    {
        _context.Entry(wallet).State = EntityState.Modified;
    }
}
