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

namespace ScadaLink.ConfigurationDatabase.Repositories;

public class InboundApiRepository : IInboundApiRepository
{
    private readonly ScadaLinkDbContext _context;

    public InboundApiRepository(ScadaLinkDbContext context)
    {
        _context = context;
    }

    public async Task<ApiKey?> GetApiKeyByIdAsync(int id, CancellationToken cancellationToken = default)
        => await _context.Set<ApiKey>().FindAsync(new object[] { id }, cancellationToken);

    public async Task<IReadOnlyList<ApiKey>> GetAllApiKeysAsync(CancellationToken cancellationToken = default)
        => await _context.Set<ApiKey>().ToListAsync(cancellationToken);

    public async Task<ApiKey?> GetApiKeyByValueAsync(string keyValue, CancellationToken cancellationToken = default)
        => await _context.Set<ApiKey>().FirstOrDefaultAsync(k => k.KeyValue == keyValue, cancellationToken);

    public async Task AddApiKeyAsync(ApiKey apiKey, CancellationToken cancellationToken = default)
        => await _context.Set<ApiKey>().AddAsync(apiKey, cancellationToken);

    public Task UpdateApiKeyAsync(ApiKey apiKey, CancellationToken cancellationToken = default)
    { _context.Set<ApiKey>().Update(apiKey); return Task.CompletedTask; }

    public async Task DeleteApiKeyAsync(int id, CancellationToken cancellationToken = default)
    {
        var entity = await GetApiKeyByIdAsync(id, cancellationToken);
        if (entity != null) _context.Set<ApiKey>().Remove(entity);
    }

    public async Task<ApiMethod?> GetApiMethodByIdAsync(int id, CancellationToken cancellationToken = default)
        => await _context.Set<ApiMethod>().FindAsync(new object[] { id }, cancellationToken);

    public async Task<IReadOnlyList<ApiMethod>> GetAllApiMethodsAsync(CancellationToken cancellationToken = default)
        => await _context.Set<ApiMethod>().ToListAsync(cancellationToken);

    public async Task<ApiMethod?> GetMethodByNameAsync(string name, CancellationToken cancellationToken = default)
        => await _context.Set<ApiMethod>().FirstOrDefaultAsync(m => m.Name == name, cancellationToken);

    public async Task<IReadOnlyList<ApiKey>> GetApprovedKeysForMethodAsync(int methodId, CancellationToken cancellationToken = default)
    {
        var method = await _context.Set<ApiMethod>().FindAsync(new object[] { methodId }, cancellationToken);
        if (method?.ApprovedApiKeyIds == null)
            return new List<ApiKey>();

        var keyIds = method.ApprovedApiKeyIds.Split(',', StringSplitOptions.RemoveEmptyEntries)
            .Select(s => int.TryParse(s.Trim(), out var id) ? id : -1)
            .Where(id => id > 0)
            .ToList();

        return await _context.Set<ApiKey>().Where(k => keyIds.Contains(k.Id)).ToListAsync(cancellationToken);
    }

    public async Task AddApiMethodAsync(ApiMethod method, CancellationToken cancellationToken = default)
        => await _context.Set<ApiMethod>().AddAsync(method, cancellationToken);

    public Task UpdateApiMethodAsync(ApiMethod method, CancellationToken cancellationToken = default)
    { _context.Set<ApiMethod>().Update(method); return Task.CompletedTask; }

    public async Task DeleteApiMethodAsync(int id, CancellationToken cancellationToken = default)
    {
        var entity = await GetApiMethodByIdAsync(id, cancellationToken);
        if (entity != null) _context.Set<ApiMethod>().Remove(entity);
    }

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