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

namespace IamService.Infrastructure.Repositories;

/// <summary>
/// EN: Repository implementation for Group aggregate.
/// VI: Repository implementation cho Group aggregate.
/// </summary>
public class GroupRepository : IGroupRepository
{
    private readonly IamServiceContext _context;

    public IUnitOfWork UnitOfWork => _context;

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

    /// <inheritdoc />
    public async Task<Group?> GetByIdAsync(Guid id, CancellationToken cancellationToken = default)
    {
        return await _context.Groups
            .Include(g => g.Members)
            .Include(g => g.Permissions)
            .FirstOrDefaultAsync(g => g.Id == id, cancellationToken);
    }

    /// <inheritdoc />
    public async Task<Group?> GetByIdWithMembersAsync(Guid id, CancellationToken cancellationToken = default)
    {
        return await _context.Groups
            .Include(g => g.Members)
            .FirstOrDefaultAsync(g => g.Id == id, cancellationToken);
    }

    /// <inheritdoc />
    public async Task<IEnumerable<Group>> GetByOrganizationIdAsync(Guid organizationId, CancellationToken cancellationToken = default)
    {
        return await _context.Groups
            .Where(g => EF.Property<Guid>(g, "_organizationId") == organizationId)
            .ToListAsync(cancellationToken);
    }

    /// <inheritdoc />
    public async Task<IEnumerable<Group>> GetByUserIdAsync(Guid userId, CancellationToken cancellationToken = default)
    {
        return await _context.Groups
            .Include(g => g.Members)
            .Where(g => g.Members.Any(m => EF.Property<Guid>(m, "_userId") == userId))
            .ToListAsync(cancellationToken);
    }

    /// <inheritdoc />
    public async Task<bool> IsUserMemberAsync(Guid groupId, Guid userId, CancellationToken cancellationToken = default)
    {
        return await _context.GroupMembers
            .AnyAsync(m =>
                EF.Property<Guid>(m, "_groupId") == groupId &&
                EF.Property<Guid>(m, "_userId") == userId,
                cancellationToken);
    }

    /// <inheritdoc />
    public Group Add(Group group)
    {
        return _context.Groups.Add(group).Entity;
    }

    /// <inheritdoc />
    public void Update(Group group)
    {
        _context.Entry(group).State = EntityState.Modified;
    }

    /// <inheritdoc />
    public void Delete(Group group)
    {
        // EN: Soft delete - just mark as deleted
        // VI: Soft delete - chỉ đánh dấu là đã xóa
        group.Delete();
        Update(group);
    }
}
