using LiteCqrs;
using TeleWave.Application.Common.Interfaces;
using TeleWave.Application.Common.Models;

namespace TeleWave.Application.Auth.Register;

public sealed class RegisterCommandHandler(
    IIdentityService identityService,
    IJwtTokenService jwtTokenService,
    IRefreshTokenService refreshTokenService,
    ISiteSettings siteSettings
) : ICommandHandler<RegisterCommand, Result<AuthResult>>
{
    public async Task<Result<AuthResult>> Handle(
        RegisterCommand command,
        CancellationToken cancellationToken
    )
    {
        // Открытая регистрация должна быть явно включена админом; иначе учётки заводит только он.
        if (!await siteSettings.IsRegistrationEnabledAsync(cancellationToken))
            return Result.Failure<AuthResult>(AuthErrors.RegistrationDisabled);

        var createResult = await identityService.CreateUserAsync(
            command.UserName,
            command.Password,
            cancellationToken
        );
        if (!createResult.IsSuccess)
            return Result.Failure<AuthResult>(createResult.Error);

        var profile = await identityService.GetProfileAsync(createResult.Value, cancellationToken);
        if (profile is null)
            return Result.Failure<AuthResult>(AuthErrors.Unauthorized);

        var (accessToken, accessExpiresAt) = jwtTokenService.GenerateAccessToken(
            new AuthenticatedUser(profile.Id, profile.UserName, profile.Role)
        );
        var refreshToken = await refreshTokenService.IssueAsync(profile.Id, cancellationToken);

        var dto = new CurrentUserDto(profile.Id, profile.UserName, profile.Role);
        return Result.Success(
            new AuthResult(
                accessToken,
                accessExpiresAt,
                refreshToken.RawToken,
                refreshToken.ExpiresAt,
                dto
            )
        );
    }
}
