using adas_core.Domain.Models.AppSettings;
using adas_core.Domain.Models.MongoModels;
using adas_core.Infrastructure.Repositories;
using Microsoft.Extensions.Options;
using MongoDB.Bson;
using MongoDB.Driver;
using Serilog;

namespace adas_core.LocalLogin;

public class LocalLoginRepository : MongoRepository<User>, ILocalLoginRepository
{
    private readonly ApiSettings _apiSettings;
    // private readonly ILogger<LocalLoginRepository> _logger;

    public LocalLoginRepository(
        IOptions<ApiSettings> apiSettings,
        IMongoDatabase database
    ) : base(database)
    {
        // _logger = logger;
        _apiSettings = apiSettings.Value;
    }
    
    public override string GetCollectionName()
    {
        return _apiSettings.Users;
    }

    public async Task<bool> InsertUserOneAsync(User user)
    {
        try
        {
            await Collection.InsertOneAsync(user);
            return true;
        }
        catch (Exception e)
        {
            Log.Error("Unable to insert user. Exception: {e}", e.Message);
            return false;
        }
    }

    public async Task<bool> UpdateOneUserAsync(ObjectId id, User user)
    {
        try
        {
            var filter = Builders<User>.Filter.Eq("Id", user.Id);
            var update = Builders<User>.Update
                .Set(c => c.Name, user.Name)
                .Set(c => c.Email, user.Email)
                .Set(c => c.UserName, user.UserName)
                .Set(c => c.Password, user.Password)
                .Set(c => c.LockExpirationDate, user.LockExpirationDate)
                .Set(c => c.LastLogin, user.LastLogin)
                .Set(c => c.IsEnabled, user.IsEnabled);
            await Collection.UpdateOneAsync(filter, update);

            return true;
        }
        catch (Exception e)
        {
            Log.Error("Unable to insert user. Exception: {e}", e.Message);
            return false;
        }
    }

    public async Task<User?> GetById(ObjectId id)
    {
        var filter = Builders<User>.Filter.Eq(p => p.Id, id);
        var result = await Collection.Find(filter).ToListAsync();
        return result.FirstOrDefault();
    }

    public async Task<User?> GetByEmail(string email)
    {
        var filter = Builders<User>.Filter.Eq(p => p.Email, email);
        var result = await Collection.Find(filter).ToListAsync();
        return result.FirstOrDefault();
    }

    public async Task<User?> GetByUsername(string username)
    {
        var filter = Builders<User>.Filter.Eq(p => p.UserName, username);
        var users = await Collection.Find(filter).ToListAsync();
        return users.FirstOrDefault();
    }

    public async Task<List<User>> GetAll()
    {
        var result = await Collection.FindAsync(Builders<User>.Filter.Empty);

        return result.ToList();
    }

    public sealed override async Task InsertInitialLoad()
    {
        await GetOrCreateSystemUser();
    }

    private async Task GetOrCreateSystemUser()
    {
        var user = await GetByUsername("System");
        if (user == null)
        {
            var userToInsert = new User
            {
                UserName = "System",
                Name = "System",
                Password = "$2a$12$crWa3EN1izcZBXNc81RzmOlfaYW2TPr2NdDQEWI7RzLTnA0Dd68WG"
            };
            await Collection.InsertOneAsync(userToInsert);
        }
    }
}