using BCrypt.Net;
using Knot.Contracts.Auth.Application.Abstractions;
using Knot.Contracts.Auth.Domain;
using Knot.Modules.Admin.Application.Admin.DTOs;
using Knot.Shared.Kernel;
using MediatR;

namespace Knot.Modules.Admin.Application.Admin.Commands.CreateUser;

public record CreateUserCommand(
    string Username,
    string Password,
    string DisplayName,
    string? Email = null,
    string? Bio = null
) : ICommand<AdminUserDto>;

internal sealed class CreateUserCommandHandler : ICommandHandler<CreateUserCommand, AdminUserDto>
{
    private readonly IUserRepository _userRepository;
    private readonly IAuthUnitOfWork _unitOfWork;

    public CreateUserCommandHandler(IUserRepository userRepository, IAuthUnitOfWork unitOfWork)
    {
        _userRepository = userRepository;
        _unitOfWork = unitOfWork;
    }

    public async Task<Result<AdminUserDto>> Handle(CreateUserCommand request, CancellationToken cancellationToken)
    {
        // Проверка уникальности username
        if (!await _userRepository.IsUsernameUniqueAsync(request.Username, cancellationToken))
        {
            return Result.Failure<AdminUserDto>(new Error("Admin.CreateUser.UsernameNotUnique", "Username is already taken"));
        }

        // Хеширование пароля
        string passwordHash = BCrypt.Net.BCrypt.HashPassword(request.Password);

        // Создание контракта пользователя
        var userContract = new UserContract
        {
            Id = Guid.NewGuid(),
            Username = request.Username,
            PasswordHash = passwordHash,
            DisplayName = request.DisplayName,
            Email = request.Email,
            Bio = request.Bio,
            CreatedAt = DateTime.UtcNow,
            IsBanned = false,
            IsOnline = false
        };

        _unitOfWork.Add(userContract);
        await _unitOfWork.SaveChangesAsync(cancellationToken);

        return Result.Success(new AdminUserDto(
            userContract.Id,
            userContract.Username,
            userContract.DisplayName,
            userContract.Email,
            userContract.Avatar,
            userContract.CreatedAt,
            userContract.IsOnline,
            userContract.LastSeen ?? DateTime.UtcNow,
            userContract.IsBanned));
    }
}
