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

namespace TeleWave.Application.Auth.Login;

public sealed class LoginCommandHandler(
    IIdentityService identityService,
    IJwtTokenService jwtTokenService,
    IRefreshTokenService refreshTokenService
) : ICommandHandler<LoginCommand, Result<AuthResult>>
{
    public async Task<Result<AuthResult>> Handle(
        LoginCommand command,
        CancellationToken cancellationToken
    )
    {
        var credentialsResult = await identityService.ValidateCredentialsAsync(
            command.UserName,
            command.Password,
            cancellationToken
        );
        if (!credentialsResult.IsSuccess)
            return Result.Failure<AuthResult>(credentialsResult.Error);

        var user = credentialsResult.Value;
        var profile = await identityService.GetProfileAsync(user.Id, cancellationToken);
        if (profile is null)
            return Result.Failure<AuthResult>(AuthErrors.InvalidCredentials);

        if (profile.IsBlocked)
            return Result.Failure<AuthResult>(AuthErrors.Blocked);

        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
            )
        );
    }
}
