using System.Net.Http.Json; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Logging; using UniVerse.Application.DTOs.Sync; using UniVerse.Application.Interfaces; namespace UniVerse.Infrastructure.ExternalServices; public class ModeusApiClient : IModeusApiClient { private readonly HttpClient _http; private readonly ILogger _logger; public ModeusApiClient(HttpClient http, IConfiguration config, ILogger logger) { _http = http; _logger = logger; var apiKey = config["ModeusApi:ApiKey"]; if (!string.IsNullOrEmpty(apiKey)) _http.DefaultRequestHeaders.Add("X-API-Key", apiKey); } public async Task SearchEventsAsync(SyncScheduleRequest request) { var body = new { specialtyCode = request.SpecialtyCode, timeMin = request.TimeMin, timeMax = request.TimeMax, typeId = request.TypeId }; var response = await _http.PostAsJsonAsync("/api/proxy/events/search", body); await EnsureSuccessAsync(response, "Modeus events search", $"specialtyCode={request.SpecialtyCode ?? ""}, timeMin={request.TimeMin:O}, timeMax={request.TimeMax:O}, typeId=[{string.Join(", ", request.TypeId ?? [])}]"); return await response.Content.ReadFromJsonAsync() ?? new(new()); } public async Task SearchRoomsAsync() { const int pageSize = 100; var allRooms = new List(); var page = 0; var totalPages = 1; do { var body = new { name = "", sort = "+building.name,+name", size = pageSize, page, deleted = false }; var response = await _http.PostAsJsonAsync("/api/proxy/rooms/search", body); await EnsureSuccessAsync(response, "Modeus rooms search", $"name=, sort=+building.name,+name, size={pageSize}, page={page}, deleted=false"); var payload = await response.Content.ReadFromJsonAsync() ?? new ModeusRoomsResponse(); allRooms.AddRange(payload.RoomItems); totalPages = payload.Page?.TotalPages ?? page + 1; page++; } while (page < totalPages); return new ModeusRoomsResponse { Rooms = allRooms }; } private static async Task EnsureSuccessAsync(HttpResponseMessage response, string operation, string requestSummary) { if (response.IsSuccessStatusCode) return; var responseBody = await response.Content.ReadAsStringAsync(); if (responseBody.Length > 2000) responseBody = string.Concat(responseBody.AsSpan(0, 2000), "..."); throw new HttpRequestException( $"{operation} failed with HTTP {(int)response.StatusCode} {response.ReasonPhrase}. Request: {requestSummary}. Response body: {responseBody}", null, response.StatusCode); } public async Task> SearchEmployeeAsync(string fullname) { var response = await _http.GetFromJsonAsync>( $"/api/schedule/searchemployee?fullname={Uri.EscapeDataString(fullname)}"); return response ?? new(); } }