using Microsoft.EntityFrameworkCore;
using Modules.User.Application.Repositories;
using Modules.User.Database.Database;
using Modules.User.Domain.Entities.Access;
using Modules.User.Domain.Factories.Access;

namespace Modules.User.Database.Repositories;

public class PermissionRepository(UserDbContext context) : IPermissionRepository
{
    public async Task<Permission?> GetByCodeAsync(string code, CancellationToken cancellationToken)
    {
        var permission = await context.Permissions
            .AsNoTracking()
            .FirstOrDefaultAsync(q => q.Code.ToLower() == code.Trim().ToLower(), cancellationToken);
        return permission == null
            ? null
            : PermissionFactory.Load(permission.Id, permission.Code,
                permission.Name, permission.Description, permission.CreationDate, permission.Deleted);
    }

    public async Task<Permission?> GetByNameAsync(string permissionName, CancellationToken cancellationToken)
    {
        var permission = await context.Permissions
            .AsNoTracking()
            .FirstOrDefaultAsync(q => q.Name.ToLower() == permissionName.Trim().ToLower(), cancellationToken);
        return permission == null
            ? null
            : PermissionFactory.Load(permission.Id, permission.Code,
                permission.Name, permission.Description, permission.CreationDate, permission.Deleted);
    }

    public async Task<Permission?> GetAsync(int permissionId, CancellationToken cancellationToken)
    {
        var permission = await context.Permissions
            .AsNoTracking()
            .FirstOrDefaultAsync(q => q.Id == permissionId, cancellationToken);
        return permission == null
            ? null
            : PermissionFactory.Load(permission.Id, permission.Code,
                permission.Name, permission.Description, permission.CreationDate, permission.Deleted);
    }

    public async ValueTask<bool> ExistsAllAsync(IEnumerable<int> permissionIds, CancellationToken cancellationToken)
    {
        var set = permissionIds.Distinct().ToArray();
        if (set.Length == 0) return true;
        var count = await context.Permissions
            .Where(p => set.Contains(p.Id) && !p.Deleted)
            .CountAsync(cancellationToken);
        return count == set.Length;
    }

    public Task AddAsync(Permission permission, CancellationToken cancellationToken = default)
    {
        var ef = new Database.Entities.Permission
        {
            Code = permission.Code,
            Name = permission.Name,
            Description = permission.Description,
            CreationDate = permission.CreationDate,
            Deleted = false,
        };
        context.Permissions.Add(ef);
        return Task.CompletedTask;
    }

    public async Task SaveAsync(Permission permission, CancellationToken ct = default)
    {
        var ef = await context.Permissions
            .FirstAsync(r => r.Id == permission.Id, ct);
        ef.Name = permission.Name;
        ef.Description = permission.Description;
        ef.Deleted = permission.Deleted;
    }
}