using Microsoft.EntityFrameworkCore;
using ScadaLink.Commons.Entities.Security;
using ScadaLink.Commons.Interfaces.Repositories;

namespace ScadaLink.ConfigurationDatabase.Repositories;

public class SecurityRepository : ISecurityRepository
{
    private readonly ScadaLinkDbContext _context;

    public SecurityRepository(ScadaLinkDbContext context)
    {
        _context = context ?? throw new ArgumentNullException(nameof(context));
    }

    // LdapGroupMapping

    public async Task<LdapGroupMapping?> GetMappingByIdAsync(int id, CancellationToken cancellationToken = default)
    {
        return await _context.LdapGroupMappings.FindAsync(new object[] { id }, cancellationToken);
    }

    public async Task<IReadOnlyList<LdapGroupMapping>> GetAllMappingsAsync(CancellationToken cancellationToken = default)
    {
        return await _context.LdapGroupMappings.ToListAsync(cancellationToken);
    }

    public async Task<IReadOnlyList<LdapGroupMapping>> GetMappingsByRoleAsync(string role, CancellationToken cancellationToken = default)
    {
        return await _context.LdapGroupMappings
            .Where(m => m.Role == role)
            .ToListAsync(cancellationToken);
    }

    public async Task AddMappingAsync(LdapGroupMapping mapping, CancellationToken cancellationToken = default)
    {
        await _context.LdapGroupMappings.AddAsync(mapping, cancellationToken);
    }

    public Task UpdateMappingAsync(LdapGroupMapping mapping, CancellationToken cancellationToken = default)
    {
        _context.LdapGroupMappings.Update(mapping);
        return Task.CompletedTask;
    }

    public async Task DeleteMappingAsync(int id, CancellationToken cancellationToken = default)
    {
        var mapping = await _context.LdapGroupMappings.FindAsync(new object[] { id }, cancellationToken);
        if (mapping != null)
        {
            _context.LdapGroupMappings.Remove(mapping);
        }
    }

    // SiteScopeRule

    public async Task<SiteScopeRule?> GetScopeRuleByIdAsync(int id, CancellationToken cancellationToken = default)
    {
        return await _context.SiteScopeRules.FindAsync(new object[] { id }, cancellationToken);
    }

    public async Task<IReadOnlyList<SiteScopeRule>> GetScopeRulesForMappingAsync(int ldapGroupMappingId, CancellationToken cancellationToken = default)
    {
        return await _context.SiteScopeRules
            .Where(r => r.LdapGroupMappingId == ldapGroupMappingId)
            .ToListAsync(cancellationToken);
    }

    public async Task AddScopeRuleAsync(SiteScopeRule rule, CancellationToken cancellationToken = default)
    {
        await _context.SiteScopeRules.AddAsync(rule, cancellationToken);
    }

    public Task UpdateScopeRuleAsync(SiteScopeRule rule, CancellationToken cancellationToken = default)
    {
        _context.SiteScopeRules.Update(rule);
        return Task.CompletedTask;
    }

    public async Task DeleteScopeRuleAsync(int id, CancellationToken cancellationToken = default)
    {
        var rule = await _context.SiteScopeRules.FindAsync(new object[] { id }, cancellationToken);
        if (rule != null)
        {
            _context.SiteScopeRules.Remove(rule);
        }
    }

    public async Task<int> SaveChangesAsync(CancellationToken cancellationToken = default)
    {
        return await _context.SaveChangesAsync(cancellationToken);
    }
}
