using Microsoft.EntityFrameworkCore;
using EonaCat.LogStack.Status.Data;

namespace EonaCat.LogStack.Status.Services;

public class AuthenticationService
{
    // This file is part of the EonaCat project(s) which is released under the Apache License.
    // See the LICENSE file or go to https://EonaCat.com/License for full license details.

    private readonly IDbContextFactory<DatabaseContext> _dbFactory;

    public AuthenticationService(IDbContextFactory<DatabaseContext> dbFactory) => _dbFactory = dbFactory;

    public async Task<bool> ValidatePasswordAsync(string password)
    {
        if (string.IsNullOrWhiteSpace(password)) 
        {
            return false;
        }

        await using var db = await _dbFactory.CreateDbContextAsync();
        var setting = await db.Settings.FirstOrDefaultAsync(s => s.Key == "AdminPasswordHash");
        if (setting == null)
        {
            return false;
        }

        return BCrypt.Net.BCrypt.EnhancedVerify(password, setting.Value);
    }

    public async Task<bool> ChangePasswordAsync(string currentPassword, string newPassword)
    {
        if (string.IsNullOrWhiteSpace(currentPassword))
        {
            return false;
        }

        if (string.IsNullOrWhiteSpace(newPassword))
        {
            return false;
        }

        if (!await ValidatePasswordAsync(currentPassword))
        {
            return false;
        }

        await using var db = await _dbFactory.CreateDbContextAsync();
        var setting = await db.Settings.FirstAsync(s => s.Key == "AdminPasswordHash");
        setting.Value = BCrypt.Net.BCrypt.EnhancedHashPassword(newPassword);
        await db.SaveChangesAsync();
        return true;
    }

    public async Task<string> GetSettingAsync(string key, string defaultValue = "")
    {
        await using var db = await _dbFactory.CreateDbContextAsync();
        var s = await db.Settings.FirstOrDefaultAsync(x => x.Key == key);
        return s?.Value ?? defaultValue;
    }

    public async Task SetSettingAsync(string key, string value)
    {
        await using var db = await _dbFactory.CreateDbContextAsync();
        var setting = await db.Settings.FirstOrDefaultAsync(x => x.Key == key);
        if (setting == null) 
        {
            db.Settings.Add(new Models.AppSettings { Key = key, Value = value }); 
        }
        else 
        {
            setting.Value = value; 
        }
        await db.SaveChangesAsync();
    }
}
