using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using OTSSignsOrchestrator.Core.Configuration; namespace OTSSignsOrchestrator.Core.Services; /// /// Tests connectivity to deployed Xibo CMS instances using OAuth2. /// public class XiboApiService { private readonly IHttpClientFactory _httpClientFactory; private readonly XiboOptions _options; private readonly ILogger _logger; public XiboApiService( IHttpClientFactory httpClientFactory, IOptions options, ILogger logger) { _httpClientFactory = httpClientFactory; _options = options.Value; _logger = logger; } public async Task TestConnectionAsync(string instanceUrl, string username, string password) { _logger.LogInformation("Testing Xibo connection to {InstanceUrl}", instanceUrl); var client = _httpClientFactory.CreateClient("XiboApi"); client.Timeout = TimeSpan.FromSeconds(_options.TestConnectionTimeoutSeconds); try { var baseUrl = instanceUrl.TrimEnd('/'); var tokenUrl = $"{baseUrl}/api/authorize/access_token"; var formContent = new FormUrlEncodedContent(new[] { new KeyValuePair("grant_type", "client_credentials"), new KeyValuePair("client_id", username), new KeyValuePair("client_secret", password) }); var response = await client.PostAsync(tokenUrl, formContent); if (response.IsSuccessStatusCode) { _logger.LogInformation("Xibo connection test succeeded for {InstanceUrl}", instanceUrl); return new XiboTestResult { IsValid = true, Message = "Connected successfully.", HttpStatus = (int)response.StatusCode }; } _logger.LogWarning("Xibo connection test failed: {InstanceUrl} | status={StatusCode}", instanceUrl, (int)response.StatusCode); return new XiboTestResult { IsValid = false, Message = response.StatusCode switch { System.Net.HttpStatusCode.Unauthorized => "Invalid Xibo credentials.", System.Net.HttpStatusCode.Forbidden => "User lacks API permissions.", System.Net.HttpStatusCode.ServiceUnavailable => "Xibo instance not ready.", _ => $"Unexpected response: {(int)response.StatusCode}" }, HttpStatus = (int)response.StatusCode }; } catch (TaskCanceledException) { return new XiboTestResult { IsValid = false, Message = "Connection timed out." }; } catch (HttpRequestException ex) { return new XiboTestResult { IsValid = false, Message = $"Cannot reach Xibo instance: {ex.Message}" }; } } } public class XiboTestResult { public bool IsValid { get; set; } public string Message { get; set; } = string.Empty; public int HttpStatus { get; set; } }