using adas_core.Application.Repositories.Interfaces;
using adas_core.Domain.Models.AppSettings;
using adas_core.Domain.Models.MongoModels;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using MongoDB.Bson;
using MongoDB.Driver;

namespace adas_core.Infrastructure.Repositories;

public class AuthorityRepository(
    IOptions<ApiSettings> apiSettings,
    IMongoDatabase database,
    ILogger<AuthorityRepository> logger)
    : MongoRepository<Authorization>(database), IAuthorityRepository
{
    private readonly ApiSettings _apiSettings = apiSettings.Value;
    private readonly ILogger _logger = logger;

    public void CreateNewAuthority(string roleName, ObjectId userId)
    {
        var newAuthorization = new Authorization
        {
            UserId = userId,
            DisplayId = ObjectId.GenerateNewId().ToString(),
            Rol = roleName
        };

        Collection.InsertOne(newAuthorization);
        _logger.LogDebug("New authority created for user {UserId} with role {RoleName}", userId, roleName);
    }

    public async Task<List<Authorization>> GetUserAuthorities(ObjectId userId)
    {
        var filter = Builders<Authorization>.Filter.Eq(p => p.UserId, userId);
        var result = await Collection.FindAsync(filter);
        _logger.LogDebug("Retrieved authorities for user {UserId}", userId);
        return result.ToList();
    }

    public async Task<List<Authorization>> GetAllAuthorities()
    {
        var result = await Collection.FindAsync(Builders<Authorization>.Filter.Empty);
        _logger.LogDebug("Retrieved all authorities");
        return result.ToList();
    }

    public async Task<List<Authorization>> GetByUnitId(ObjectId unitId)
    {
        var filter = Builders<Authorization>.Filter.Eq(a => a.UnitId, unitId.ToString());

        var result = await Collection.FindAsync(filter);

        _logger.LogDebug("Retrieved authorities for unit {UnitId}", unitId);

        return result.ToList();
    }

    public async Task<bool> DeleteAllAuthoritiesByUser(ObjectId userId)
    {
        try
        {
            var filter = Builders<Authorization>.Filter.Eq(p => p.UserId, userId);
            await Collection.DeleteManyAsync(filter);

            _logger.LogDebug("Deleted all authorities for user {UserId}", userId);

            return true;
        }
        catch (Exception)
        {
            return false;
        }
    }


    public async Task<bool> DeleteAllAuthoritiesByUnit(ObjectId unitId)
    {
        try
        {
            var filter = Builders<Authorization>.Filter.Eq(p => p.UnitId, unitId.ToString());
            await Collection.DeleteManyAsync(filter);
            _logger.LogDebug("Deleted all authorities for unit {UnitId}", unitId);
            return true;
        }
        catch (Exception)
        {
            return false;
        }
    }

    public async Task<bool> DeleteAllAuthoritiesByDisplay(ObjectId displayId)
    {
        try
        {
            var filter = Builders<Authorization>.Filter.Eq(p => p.DisplayId, displayId.ToString());
            await Collection.DeleteManyAsync(filter);
            _logger.LogDebug("Deleted all authorities for display {DisplayId}", displayId);
            return true;
        }
        catch (Exception)
        {
            return false;
        }
    }

    public override string GetCollectionName()
    {
        return _apiSettings.Authorizations;
    }

    public async Task<Authorization> GetById(ObjectId authId)
    {
        var filter = Builders<Authorization>.Filter.Eq(p => p.Id, authId);
        return await Collection.Find(filter).FirstOrDefaultAsync();
    }

    public sealed override async Task InsertInitialLoad()
    {
        var user = Db.GetCollection<User>(apiSettings.Value.Users);
        var filter = Builders<User>.Filter.Eq(p => p.UserName, "System");
        var search = await user.FindAsync(filter);
        var systemUSer = search.FirstOrDefault();
        if (systemUSer != null)
        {
            var auths = await GetUserAuthorities(systemUSer.Id);
            if (!auths.Exists(c => c.PanelAuthorization))
                await InsertOneAsync(new Authorization
                    { CanUpdate = false, PanelAuthorization = true, Rol = "AuthAdmin", UserId = systemUSer.Id });
        }
    }
}