using System; using System.Collections.Generic; using System.Linq; using System.Net.Http; using System.Text; using System.Threading.Tasks; using System.Net.Http.Json; using System.Text.Json; using System.Text.Json.Serialization; namespace Электронная_Фармация.Classes { public class ApiClient { private readonly HttpClient _httpClient; private readonly string _baseUrl; private string _token; public ApiClient(string baseUrl = null) { _baseUrl = (baseUrl ?? AppConfig.ApiBaseUrl).TrimEnd('/'); _httpClient = new HttpClient { BaseAddress = new Uri(_baseUrl), Timeout = TimeSpan.FromSeconds(30) }; } /// /// Выполняет авторизацию и сохраняет токен /// /// Имя пользователя /// Пароль /// JWT токен /// При ошибке авторизации public async Task LoginAsync(string username, string password) { var request = new LoginRequest { Username = username, Password = password }; try { var response = await _httpClient.PostAsJsonAsync("/auth/login", request); if (response.IsSuccessStatusCode) { var loginResponse = await response.Content.ReadFromJsonAsync(); _token = loginResponse.Token; return _token; } else if (response.StatusCode == System.Net.HttpStatusCode.Unauthorized) { var error = await response.Content.ReadFromJsonAsync(); throw new UnauthorizedAccessException($"Ошибка авторизации: {error?.Error ?? "Неверные учетные данные"}"); } else { var error = await response.Content.ReadFromJsonAsync(); throw new HttpRequestException($"Ошибка HTTP {response.StatusCode}: {error?.Error ?? "Неизвестная ошибка"}"); } } catch (TaskCanceledException) { throw new HttpRequestException("Превышено время ожидания ответа сервера"); } } /// /// Устанавливает токен для последующих запросов /// public void SetToken(string token) { _token = token; } public string Token => _token; /// /// Проверяет, авторизован ли клиент /// public bool IsAuthenticated => !string.IsNullOrEmpty(_token); public async Task GetPriceSummaryAsync(string supplierId = null, string regionId = null) { if (!IsAuthenticated) { throw new InvalidOperationException("Необходимо выполнить авторизацию перед запросом данных"); } var queryParams = new List(); if (!string.IsNullOrEmpty(supplierId)) { queryParams.Add($"supplier_id={Uri.EscapeDataString(supplierId)}"); } if (!string.IsNullOrEmpty(regionId)) { queryParams.Add($"region_id={Uri.EscapeDataString(regionId)}"); } var url = "/api/supplier-prices/summary"; if (queryParams.Count > 0) { url += "?" + string.Join("&", queryParams); } _httpClient.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", _token); try { var response = await _httpClient.GetAsync(url); if (response.IsSuccessStatusCode) { var summary = await response.Content.ReadFromJsonAsync(); return summary; } else if (response.StatusCode == System.Net.HttpStatusCode.Unauthorized) { _token = null; // Токен истек или невалиден var error = await response.Content.ReadFromJsonAsync(); throw new UnauthorizedAccessException($"Сессия истекла: {error?.Error ?? "Необходимо войти заново"}"); } else { var error = await response.Content.ReadFromJsonAsync(); throw new HttpRequestException($"Ошибка HTTP {response.StatusCode}: {error?.Error ?? "Неизвестная ошибка"}"); } } catch (TaskCanceledException) { throw new HttpRequestException("Превышено время ожидания ответа сервера (таймаут 30 секунд)"); } } public async Task> GetInvoicesAsync() { if (!IsAuthenticated) { throw new InvalidOperationException("Необходимо выполнить авторизацию перед запросом накладных"); } _httpClient.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", _token); var response = await _httpClient.GetAsync("/api/buyer/invoices"); var body = await response.Content.ReadAsStringAsync(); if (!response.IsSuccessStatusCode) { throw new HttpRequestException( $"Ошибка загрузки накладных: {(int)response.StatusCode} {response.ReasonPhrase}\n{body}"); } return JsonSerializer.Deserialize>(body) ?? new List(); } } public sealed class InvoiceApiItem { public string InvoiceNumber { get; set; } public string InvoiceDate { get; set; } public string SupplierName { get; set; } public string ConsigneeName { get; set; } public string InvoiceSum { get; set; } public string RefuseSum { get; set; } } }