using Microsoft.EntityFrameworkCore;
using MembershipService.Domain.AggregatesModel.MemberAggregate;
using MembershipService.Domain.SeedWork;

namespace MembershipService.Infrastructure.Repositories;

/// <summary>
/// EN: Repository implementation for Member aggregate.
/// VI: Repository implementation cho Member aggregate.
/// </summary>
public class MemberRepository : IMemberRepository
{
    private readonly MembershipServiceContext _context;

    public MemberRepository(MembershipServiceContext context)
    {
        _context = context ?? throw new ArgumentNullException(nameof(context));
    }

    public IUnitOfWork UnitOfWork => _context;

    /// <summary>
    /// EN: Get member by ID.
    /// VI: Lấy member theo ID.
    /// </summary>
    public async Task<Member?> GetByIdAsync(Guid id, CancellationToken cancellationToken = default)
    {
        return await _context.Members
            .FirstOrDefaultAsync(m => m.Id == id, cancellationToken);
    }

    /// <summary>
    /// EN: Get member by User ID (same as member ID).
    /// VI: Lấy member theo User ID (giống member ID).
    /// </summary>
    public async Task<Member?> GetByUserIdAsync(Guid userId, CancellationToken cancellationToken = default)
    {
        // EN: UserId is same as Member.Id
        // VI: UserId giống với Member.Id
        return await GetByIdAsync(userId, cancellationToken);
    }

    /// <summary>
    /// EN: Get paginated list of members.
    /// VI: Lấy danh sách members phân trang.
    /// </summary>
    public async Task<(IEnumerable<Member> Members, int TotalCount)> GetPaginatedAsync(
        int pageIndex,
        int pageSize,
        string? searchTerm = null,
        CancellationToken cancellationToken = default)
    {
        var query = _context.Members.AsQueryable();

        // EN: Apply search filter if provided (search by country code or gender)
        // VI: Áp dụng filter tìm kiếm nếu có (tìm theo country code hoặc gender)
        if (!string.IsNullOrWhiteSpace(searchTerm))
        {
            query = query.Where(m =>
                m.CountryCode.Contains(searchTerm) ||
                (m.Gender != null && m.Gender.Contains(searchTerm)));
        }

        var totalCount = await query.CountAsync(cancellationToken);

        var members = await query
            .OrderByDescending(m => EF.Property<DateTime>(m, "_createdAt"))
            .Skip(pageIndex * pageSize)
            .Take(pageSize)
            .ToListAsync(cancellationToken);

        return (members, totalCount);
    }

    /// <summary>
    /// EN: Check if member exists for user.
    /// VI: Kiểm tra member có tồn tại cho user không.
    /// </summary>
    public async Task<bool> ExistsForUserAsync(Guid userId, CancellationToken cancellationToken = default)
    {
        return await _context.Members
            .AnyAsync(m => m.Id == userId, cancellationToken);
    }

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

    /// <summary>
    /// EN: Update member.
    /// VI: Cập nhật member.
    /// </summary>
    public void Update(Member member)
    {
        _context.Entry(member).State = EntityState.Modified;
    }

    /// <summary>
    /// EN: Delete member (soft delete).
    /// VI: Xóa member (xóa mềm).
    /// </summary>
    public void Delete(Member member)
    {
        member.Delete();
        Update(member);
    }
}
