using IamService.Domain.SeedWork;

namespace IamService.Domain.AggregatesModel.GroupAggregate;

/// <summary>
/// EN: Group permission entity representing permissions granted to a group.
/// VI: Entity quyền nhóm đại diện cho quyền được cấp cho nhóm.
/// </summary>
public class GroupPermission : Entity
{
    // EN: Private fields for encapsulation
    // VI: Fields private để đóng gói
    private Guid _groupId;
    private string _permission = null!;
    private string? _resource;
    private DateTime _grantedAt;
    private Guid? _grantedByUserId;

    /// <summary>
    /// EN: Group ID this permission belongs to.
    /// VI: ID nhóm mà quyền thuộc về.
    /// </summary>
    public Guid GroupId => _groupId;

    /// <summary>
    /// EN: Permission name (e.g., "read", "write", "delete", "admin").
    /// VI: Tên quyền (ví dụ: "read", "write", "delete", "admin").
    /// </summary>
    public string Permission => _permission;

    /// <summary>
    /// EN: Optional resource the permission applies to (e.g., "projects/*", "users/123").
    /// VI: Resource tùy chọn mà quyền áp dụng (ví dụ: "projects/*", "users/123").
    /// </summary>
    public string? Resource => _resource;

    /// <summary>
    /// EN: When the permission was granted.
    /// VI: Thời điểm quyền được cấp.
    /// </summary>
    public DateTime GrantedAt => _grantedAt;

    /// <summary>
    /// EN: Who granted this permission.
    /// VI: Ai đã cấp quyền này.
    /// </summary>
    public Guid? GrantedByUserId => _grantedByUserId;

    /// <summary>
    /// EN: Private constructor for EF Core.
    /// VI: Constructor private cho EF Core.
    /// </summary>
    protected GroupPermission()
    {
    }

    /// <summary>
    /// EN: Create a new group permission.
    /// VI: Tạo quyền nhóm mới.
    /// </summary>
    public GroupPermission(Guid groupId, string permission, string? resource = null, Guid? grantedByUserId = null) : this()
    {
        if (groupId == Guid.Empty)
            throw new ArgumentException("Group ID cannot be empty", nameof(groupId));
        if (string.IsNullOrWhiteSpace(permission))
            throw new ArgumentException("Permission cannot be empty", nameof(permission));

        Id = Guid.NewGuid();
        _groupId = groupId;
        _permission = permission.ToLowerInvariant().Trim();
        _resource = resource?.Trim();
        _grantedAt = DateTime.UtcNow;
        _grantedByUserId = grantedByUserId;
    }

    /// <summary>
    /// EN: Check if this permission matches a given permission and resource.
    /// VI: Kiểm tra quyền này có khớp với quyền và resource cho trước không.
    /// </summary>
    public bool Matches(string permission, string? resource = null)
    {
        if (!string.Equals(_permission, permission, StringComparison.OrdinalIgnoreCase))
            return false;

        // EN: If no specific resource is required, match any
        // VI: Nếu không yêu cầu resource cụ thể, khớp với bất kỳ
        if (string.IsNullOrEmpty(resource))
            return true;

        // EN: If this permission has no resource restriction, it applies to all
        // VI: Nếu quyền này không có giới hạn resource, nó áp dụng cho tất cả
        if (string.IsNullOrEmpty(_resource))
            return true;

        // EN: Check for wildcard match
        // VI: Kiểm tra khớp với wildcard
        if (_resource.EndsWith("/*"))
        {
            var prefix = _resource[..^2];
            return resource.StartsWith(prefix, StringComparison.OrdinalIgnoreCase);
        }

        return string.Equals(_resource, resource, StringComparison.OrdinalIgnoreCase);
    }
}
