using FastBlog.Core.Abstractions.Repositories.Users;
using FastBlog.Core.Models;
using FastBlog.Core.Models.Users;

namespace FastBlog.Core.Services;

public sealed class UserService(IUserRepository repository)
{
    public Task<User?> Get(int id) => repository.Get(id);
    
    public async Task<User?> GetByName(string username)
    {
        return User.FromUserPassword(await repository.GetByName(username));
    }
    
    public async Task<User?> GetByCredentials(string username, string password)
    {
        var user = await repository.GetByName(username);
        if (user is null || user.Deleted) return null;
        
        return !BCrypt.Net.BCrypt.Verify(password, user.PasswordHash) ? null : User.FromUserPassword(user);
    }

    public sealed record ChangePasswordResult(bool Success, string Message); 
    public async Task<ChangePasswordResult> ChangePassword(int id, string oldPassword, string newPassword)
    {
        var user = await repository.GetWithPassword(id);
        if (user is null)
            return new(false, "Unknown user");
        if (!BCrypt.Net.BCrypt.Verify(oldPassword, user.PasswordHash))
            return new(false, "Wrong password");
        if (!await repository.SetPassword(id, BCrypt.Net.BCrypt.HashPassword(newPassword)))
            return new(false, "Couldn't update password");
        return new(true, "Successfully updated the password");
    }
    
    public async Task<ChangePasswordResult> SetPassword(int id, string newPassword)
    {
        var user = await repository.GetWithPassword(id);
        if (user is null)
            return new(false, "Unknown user");
        if (!await repository.SetPassword(id, BCrypt.Net.BCrypt.HashPassword(newPassword)))
            return new(false, "Couldn't update password");
        return new(true, "Successfully updated the password");
    }
    
    public Task<PagedResponse<User>> GetUsers(PagedRequest pagedRequest) => repository.GetUsers(pagedRequest);

    public Task<User> CreateUser(NewUser newUser)
    {
        newUser.Password = BCrypt.Net.BCrypt.HashPassword(newUser.Password);
        return repository.CreateUser(newUser);
    }
    
    public async Task<bool> DeleteUser(int userId) => await repository.DeleteUser(userId);
}