using Microsoft.EntityFrameworkCore;
using SocialService.Domain.AggregatesModel.UserProfileAggregate;
using SocialService.Domain.SeedWork;

namespace SocialService.Infrastructure.Repositories;

/// <summary>
/// EN: Repository implementation for UserProfile aggregate.
/// VI: Implementation repository cho UserProfile aggregate.
/// </summary>
public class UserProfileRepository : IUserProfileRepository
{
    private readonly SocialServiceContext _context;

    public IUnitOfWork UnitOfWork => _context;

    public UserProfileRepository(SocialServiceContext context)
    {
        _context = context ?? throw new ArgumentNullException(nameof(context));
    }

    public UserProfile Add(UserProfile userProfile)
    {
        return _context.UserProfiles.Add(userProfile).Entity;
    }

    public UserProfile Update(UserProfile userProfile)
    {
        return _context.UserProfiles.Update(userProfile).Entity;
    }

    public async Task<UserProfile?> GetByIdAsync(Guid id)
    {
        return await _context.UserProfiles.FindAsync(id);
    }

    public async Task<UserProfile?> GetByUserIdAsync(Guid userId)
    {
        return await _context.UserProfiles
            .FirstOrDefaultAsync(up => EF.Property<Guid>(up, "_userId") == userId);
    }

    public async Task<IEnumerable<UserProfile>> SearchByDisplayNameAsync(string searchTerm, int skip = 0, int take = 20)
    {
        return await _context.UserProfiles
            .Where(up => EF.Property<string>(up, "_displayName").ToLower().Contains(searchTerm.ToLower()))
            .OrderBy(up => EF.Property<string>(up, "_displayName"))
            .Skip(skip)
            .Take(take)
            .ToListAsync();
    }

    public async Task<IEnumerable<UserProfile>> GetByUserIdsAsync(IEnumerable<Guid> userIds)
    {
        var userIdList = userIds.ToList();
        return await _context.UserProfiles
            .Where(up => userIdList.Contains(EF.Property<Guid>(up, "_userId")))
            .ToListAsync();
    }

    public async Task<bool> ExistsAsync(Guid userId)
    {
        return await _context.UserProfiles
            .AnyAsync(up => EF.Property<Guid>(up, "_userId") == userId);
    }
}
