using Microsoft.EntityFrameworkCore;
using IamService.Domain.AggregatesModel.UserAggregate;
using IamService.Domain.SeedWork;

namespace IamService.Infrastructure.Repositories;

/// <summary>
/// EN: Repository implementation for ApplicationUser aggregate.
/// VI: Repository implementation cho ApplicationUser aggregate.
/// </summary>
public class UserRepository : IUserRepository
{
    private readonly IamServiceContext _context;

    public UserRepository(IamServiceContext context)
    {
        _context = context ?? throw new ArgumentNullException(nameof(context));
    }

    public IUnitOfWork UnitOfWork => _context;

    /// <summary>
    /// EN: Find user by email.
    /// VI: Tìm user theo email.
    /// </summary>
    public async Task<ApplicationUser?> FindByEmailAsync(string email, CancellationToken cancellationToken = default)
    {
        return await _context.Users
            .FirstOrDefaultAsync(u => u.NormalizedEmail == email.ToUpperInvariant(), cancellationToken);
    }

    /// <summary>
    /// EN: Find user by ID.
    /// VI: Tìm user theo ID.
    /// </summary>
    public async Task<ApplicationUser?> FindByIdAsync(Guid id, CancellationToken cancellationToken = default)
    {
        return await _context.Users
            .FirstOrDefaultAsync(u => u.Id == id, cancellationToken);
    }

    /// <summary>
    /// EN: Get all users with pagination.
    /// VI: Lấy tất cả users với phân trang.
    /// </summary>
    public async Task<(IEnumerable<ApplicationUser> Users, int TotalCount)> GetAllAsync(
        int pageNumber,
        int pageSize,
        CancellationToken cancellationToken = default)
    {
        var query = _context.Users.AsQueryable();

        var totalCount = await query.CountAsync(cancellationToken);

        var users = await query
            .OrderByDescending(u => u.CreatedAt)
            .Skip((pageNumber - 1) * pageSize)
            .Take(pageSize)
            .ToListAsync(cancellationToken);

        return (users, totalCount);
    }

    /// <summary>
    /// EN: Add new user.
    /// VI: Thêm user mới.
    /// </summary>
    public ApplicationUser Add(ApplicationUser user)
    {
        return _context.Users.Add(user).Entity;
    }

    /// <summary>
    /// EN: Update existing user.
    /// VI: Cập nhật user hiện có.
    /// </summary>
    public void Update(ApplicationUser user)
    {
        _context.Entry(user).State = EntityState.Modified;
    }
}
