using Microsoft.EntityFrameworkCore;
using MiningService.Domain.AggregatesModel.MinerAggregate;
using MiningService.Domain.SeedWork;

namespace MiningService.Infrastructure.Repositories;

/// <summary>
/// EN: Repository implementation for Miner aggregate.
/// VI: Triển khai repository cho Miner aggregate.
/// </summary>
public class MinerRepository : IMinerRepository
{
    private readonly MiningServiceContext _context;

    public IUnitOfWork UnitOfWork => _context;

    public MinerRepository(MiningServiceContext context)
    {
        _context = context ?? throw new ArgumentNullException(nameof(context));
    }

    public async Task<Miner?> GetByIdAsync(Guid id, CancellationToken cancellationToken = default)
    {
        return await _context.Miners
            .Include(m => m.MiningHistories.OrderByDescending(h => h.EarnedAt).Take(50))
            .FirstOrDefaultAsync(m => m.Id == id, cancellationToken);
    }

    public async Task<Miner?> GetByUserIdAsync(Guid userId, CancellationToken cancellationToken = default)
    {
        return await _context.Miners
            .FirstOrDefaultAsync(m => m.UserId == userId, cancellationToken);
    }

    public async Task<Miner?> GetByReferralCodeAsync(string referralCode, CancellationToken cancellationToken = default)
    {
        return await _context.Miners
            .FirstOrDefaultAsync(m => m.ReferralCode == referralCode, cancellationToken);
    }

    public Miner Add(Miner miner)
    {
        return _context.Miners.Add(miner).Entity;
    }

    public void Update(Miner miner)
    {
        _context.Entry(miner).State = EntityState.Modified;
    }

    public async Task<bool> ReferralCodeExistsAsync(string referralCode, CancellationToken cancellationToken = default)
    {
        return await _context.Miners
            .AnyAsync(m => m.ReferralCode == referralCode, cancellationToken);
    }

    public async Task<int> GetActiveReferralsCountAsync(Guid minerId, CancellationToken cancellationToken = default)
    {
        return await _context.Referrals
            .CountAsync(r => r.ReferrerId == minerId && r.IsActive, cancellationToken);
    }

    public async Task<List<Miner>> GetTopMinersAsync(int limit, CancellationToken cancellationToken = default)
    {
        return await _context.Miners
            .OrderByDescending(m => m.TotalMinedPoints)
            .Take(limit)
            .ToListAsync(cancellationToken);
    }
}
