using PostFundManagement.Domain.Errors; using PostFundManagement.Domain.Security.Configuration; using PostFundManagement.Domain.Security.Models; using PostFundManagement.Domain.Security.Sdk; namespace PostFundManagement.Application.Services.Shared; public sealed class TokenService(ISecurityConnectApi connectApi, IOptions clientOptions) { private readonly SecurityClientSettings clientSettings = clientOptions.Value; public async ValueTask> GenerateAsync(CancellationToken cancellationToken = default) => await Result.Try((Func>>)(async () => { using var response = await connectApi.GetToken(new Domain.Security.Models.TokenRequest { ClientId = clientSettings.ClientId, ClientSecret = clientSettings.ClientSecret, GrantType = clientSettings.GrantType, Scope = clientSettings.Scope, }, cancellationToken); var contentRaw = await response.Content.ReadAsStringAsync(cancellationToken); if (string.IsNullOrWhiteSpace(contentRaw)) return Result.Fail(ValidationError.Create($"The authentication endpoint returned an empty payload. Status code: {response.StatusCode}")); if (response.IsSuccessStatusCode) { var tokenResponse = JsonSerializer.Deserialize(contentRaw); return !string.IsNullOrWhiteSpace(tokenResponse?.AccessToken) ? Result.Ok(tokenResponse) : Result.Fail(NotFoundError.Create("Authentication succeeded, but no access token was found in the response payload.")); } return await Result.Try((Func>>)(async () => { var errorResult = JsonSerializer.Deserialize(contentRaw); return Result.FailIf(errorResult != null, CreateError.Create($"{errorResult!.Error}: {errorResult.ErrorDescription}")); })); })); }