using PostFundManagement.Domain.Api.Configuration; using PostFundManagement.Domain.Api.Models; using PostFundManagement.Domain.Sdk; namespace PostFundManagement.Domain.Services; public sealed class TokenService(ISecurityConnectApi connectApi, IOptions clientOptions) { private readonly SecurityClientSettings clientSettings = clientOptions.Value; public async Task> GenerateAsync(CancellationToken cancellationToken = default) { try { var request = new Api.Models.TokenRequest { ClientId = clientSettings.ClientId, ClientSecret = clientSettings.ClientSecret, GrantType = clientSettings.GrantType, Scope = clientSettings.Scope, }; using var response = await connectApi.GetToken(request, cancellationToken); var contentRaw = await response.Content.ReadAsStringAsync(cancellationToken); if (string.IsNullOrWhiteSpace(contentRaw)) return Result.Fail(new Error($"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(new Error("Authentication succeeded, but no access token was found in the response payload.")); } try { var errorResult = JsonSerializer.Deserialize(contentRaw); if (errorResult != null) { string summary = $"{errorResult.Error}: {errorResult.ErrorDescription}"; return Result.Fail(new Error(summary)); } } catch { return Result.Fail(new Error($"Authentication failed: {contentRaw}")); } return Result.Fail(new Error($"Authentication failed with status code: {response.StatusCode}")); } catch (OperationCanceledException ex) { return Result.Fail(new Error("The token generation request was canceled.").CausedBy(ex)); } catch (Exception ex) { return Result.Fail(new Error(ex.Message).CausedBy(ex)); } } }