| 
									
										
										
										
											2025-08-14 15:27:45 -03:00
										 |  |  | using Elecciones.Core.DTOs; | 
					
						
							|  |  |  | using Microsoft.Extensions.Configuration; | 
					
						
							|  |  |  | using System.Collections.Generic; | 
					
						
							|  |  |  | using System.Net.Http; | 
					
						
							|  |  |  | using System.Net.Http.Json; | 
					
						
							| 
									
										
										
										
											2025-08-19 14:23:51 -03:00
										 |  |  | using System.Text.Json; | 
					
						
							|  |  |  | using Microsoft.Extensions.Logging; | 
					
						
							| 
									
										
										
										
											2025-08-14 15:27:45 -03:00
										 |  |  | using System.Threading.Tasks; | 
					
						
							| 
									
										
										
										
											2025-08-15 17:31:51 -03:00
										 |  |  | using static Elecciones.Core.DTOs.BancaDto; | 
					
						
							| 
									
										
										
										
											2025-08-14 15:27:45 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | namespace Elecciones.Infrastructure.Services; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | public class ElectoralApiService : IElectoralApiService | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     private readonly IHttpClientFactory _httpClientFactory; | 
					
						
							|  |  |  |     private readonly IConfiguration _configuration; | 
					
						
							| 
									
										
										
										
											2025-08-19 14:23:51 -03:00
										 |  |  |     private readonly ILogger<ElectoralApiService> _logger; | 
					
						
							| 
									
										
										
										
											2025-08-14 15:27:45 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-08-19 14:23:51 -03:00
										 |  |  |     public ElectoralApiService(IHttpClientFactory httpClientFactory, | 
					
						
							|  |  |  |     IConfiguration configuration, | 
					
						
							|  |  |  |         ILogger<ElectoralApiService> logger) | 
					
						
							| 
									
										
										
										
											2025-08-14 15:27:45 -03:00
										 |  |  |     { | 
					
						
							|  |  |  |         _httpClientFactory = httpClientFactory; | 
					
						
							|  |  |  |         _configuration = configuration; | 
					
						
							| 
									
										
										
										
											2025-08-19 14:23:51 -03:00
										 |  |  |         _logger = logger; | 
					
						
							| 
									
										
										
										
											2025-08-14 15:27:45 -03:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     public async Task<string?> GetAuthTokenAsync() | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         var client = _httpClientFactory.CreateClient("ElectoralApiClient"); | 
					
						
							|  |  |  |         var username = _configuration["ElectoralApi:Username"]; | 
					
						
							|  |  |  |         var password = _configuration["ElectoralApi:Password"]; | 
					
						
							|  |  |  |         if (string.IsNullOrEmpty(username) || string.IsNullOrEmpty(password)) return null; | 
					
						
							| 
									
										
										
										
											2025-08-16 13:30:05 -03:00
										 |  |  |         var request = new HttpRequestMessage(HttpMethod.Get, "/api/createtoken/"); | 
					
						
							| 
									
										
										
										
											2025-08-14 15:27:45 -03:00
										 |  |  |         request.Headers.Add("username", username); | 
					
						
							|  |  |  |         request.Headers.Add("password", password); | 
					
						
							|  |  |  |         var response = await client.SendAsync(request); | 
					
						
							|  |  |  |         if (!response.IsSuccessStatusCode) return null; | 
					
						
							|  |  |  |         var tokenResponse = await response.Content.ReadFromJsonAsync<TokenResponse>(); | 
					
						
							| 
									
										
										
										
											2025-08-16 13:30:05 -03:00
										 |  |  |         return (tokenResponse is { Success: true, Data.AccessToken: not null }) ? tokenResponse.Data.AccessToken : null; | 
					
						
							| 
									
										
										
										
											2025-08-14 15:27:45 -03:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-08-16 12:00:51 -03:00
										 |  |  |     public async Task<CatalogoDto?> GetCatalogoAmbitosAsync(string authToken, int categoriaId) | 
					
						
							| 
									
										
										
										
											2025-08-14 15:27:45 -03:00
										 |  |  |     { | 
					
						
							|  |  |  |         var client = _httpClientFactory.CreateClient("ElectoralApiClient"); | 
					
						
							| 
									
										
										
										
											2025-08-16 11:47:10 -03:00
										 |  |  |         var request = new HttpRequestMessage(HttpMethod.Get, $"/api/catalogo/getCatalogo?categoriaId={categoriaId}"); | 
					
						
							| 
									
										
										
										
											2025-08-14 15:27:45 -03:00
										 |  |  |         request.Headers.Add("Authorization", $"Bearer {authToken}"); | 
					
						
							|  |  |  |         var response = await client.SendAsync(request); | 
					
						
							| 
									
										
										
										
											2025-08-16 13:30:05 -03:00
										 |  |  |         return response.IsSuccessStatusCode ? await response.Content.ReadFromJsonAsync<CatalogoDto>() : null; | 
					
						
							| 
									
										
										
										
											2025-08-14 15:27:45 -03:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     public async Task<List<AgrupacionDto>?> GetAgrupacionesAsync(string authToken, string distritoId, int categoriaId) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         var client = _httpClientFactory.CreateClient("ElectoralApiClient"); | 
					
						
							| 
									
										
										
										
											2025-08-16 13:30:05 -03:00
										 |  |  |         var requestUri = $"/api/catalogo/getAgrupaciones?distritoId={distritoId}&categoriaId={categoriaId}"; | 
					
						
							| 
									
										
										
										
											2025-08-14 15:27:45 -03:00
										 |  |  |         var request = new HttpRequestMessage(HttpMethod.Get, requestUri); | 
					
						
							|  |  |  |         request.Headers.Add("Authorization", $"Bearer {authToken}"); | 
					
						
							|  |  |  |         var response = await client.SendAsync(request); | 
					
						
							| 
									
										
										
										
											2025-08-16 13:30:05 -03:00
										 |  |  |         return response.IsSuccessStatusCode ? await response.Content.ReadFromJsonAsync<List<AgrupacionDto>>() : null; | 
					
						
							| 
									
										
										
										
											2025-08-14 15:27:45 -03:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-08-17 20:08:38 -03:00
										 |  |  |     public async Task<ResultadosDto?> GetResultadosAsync(string authToken, string distritoId, string seccionId, string? municipioId, int categoriaId) | 
					
						
							| 
									
										
										
										
											2025-08-14 15:27:45 -03:00
										 |  |  |     { | 
					
						
							|  |  |  |         var client = _httpClientFactory.CreateClient("ElectoralApiClient"); | 
					
						
							| 
									
										
										
										
											2025-08-17 20:08:38 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  |         // Construimos la URL base | 
					
						
							|  |  |  |         var requestUri = $"/api/resultados/getResultados?distritoId={distritoId}&seccionId={seccionId}&categoriaId={categoriaId}"; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // Añadimos el municipioId a la URL SÓLO si no es nulo o vacío | 
					
						
							|  |  |  |         if (!string.IsNullOrEmpty(municipioId)) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             requestUri += $"&municipioId={municipioId}"; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-08-14 15:27:45 -03:00
										 |  |  |         var request = new HttpRequestMessage(HttpMethod.Get, requestUri); | 
					
						
							|  |  |  |         request.Headers.Add("Authorization", $"Bearer {authToken}"); | 
					
						
							|  |  |  |         var response = await client.SendAsync(request); | 
					
						
							| 
									
										
										
										
											2025-08-16 13:30:05 -03:00
										 |  |  |         return response.IsSuccessStatusCode ? await response.Content.ReadFromJsonAsync<ResultadosDto>() : null; | 
					
						
							| 
									
										
										
										
											2025-08-15 17:31:51 -03:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-08-19 09:37:13 -03:00
										 |  |  |     public async Task<RepartoBancasDto?> GetBancasAsync(string authToken, string distritoId, string? seccionProvincialId, int categoriaId) | 
					
						
							| 
									
										
										
										
											2025-08-15 17:31:51 -03:00
										 |  |  |     { | 
					
						
							|  |  |  |         var client = _httpClientFactory.CreateClient("ElectoralApiClient"); | 
					
						
							| 
									
										
										
										
											2025-08-19 09:37:13 -03:00
										 |  |  |         var requestUri = $"/api/resultados/getBancas?distritoId={distritoId}&categoriaId={categoriaId}"; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (!string.IsNullOrEmpty(seccionProvincialId)) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             requestUri += $"&seccionProvincialId={seccionProvincialId}"; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-08-15 17:31:51 -03:00
										 |  |  |         var request = new HttpRequestMessage(HttpMethod.Get, requestUri); | 
					
						
							|  |  |  |         request.Headers.Add("Authorization", $"Bearer {authToken}"); | 
					
						
							| 
									
										
										
										
											2025-08-19 18:33:54 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  |         HttpResponseMessage response; | 
					
						
							|  |  |  |         try | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             response = await client.SendAsync(request); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         catch (Exception ex) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             // Captura errores de red (ej. la API se cae momentáneamente) | 
					
						
							|  |  |  |             _logger.LogError(ex, "La petición HTTP a getBancas falló. URI: {requestUri}", requestUri); | 
					
						
							|  |  |  |             return null; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // Comprobamos que la respuesta fue exitosa Y que contiene datos antes de intentar leerla. | 
					
						
							|  |  |  |         if (response.IsSuccessStatusCode && response.Content?.Headers.ContentLength > 0) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             try | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |                 // Solo si hay contenido, intentamos deserializar. | 
					
						
							|  |  |  |                 return await response.Content.ReadFromJsonAsync<RepartoBancasDto>(); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             catch (JsonException ex) | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |                 // Si el contenido no es un JSON válido, lo registramos y devolvemos null. | 
					
						
							|  |  |  |                 _logger.LogWarning(ex, "La API devolvió una respuesta no-JSON para getBancas. URI: {requestUri}, Status: {statusCode}", requestUri, response.StatusCode); | 
					
						
							|  |  |  |                 return null; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         else if (!response.IsSuccessStatusCode) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             // Si la API devolvió un error HTTP, lo registramos. | 
					
						
							|  |  |  |             _logger.LogWarning("La API devolvió un código de error {statusCode} para getBancas. URI: {requestUri}", response.StatusCode, requestUri); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // Si la respuesta fue 200 OK pero con cuerpo vacío, o si fue un error HTTP, devolvemos null. | 
					
						
							|  |  |  |         return null; | 
					
						
							| 
									
										
										
										
											2025-08-15 17:31:51 -03:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-08-19 14:07:19 -03:00
										 |  |  |     public async Task<List<string>?> GetTelegramasTotalizadosAsync(string authToken, string distritoId, string seccionId, int? categoriaId = null) | 
					
						
							| 
									
										
										
										
											2025-08-15 17:31:51 -03:00
										 |  |  |     { | 
					
						
							|  |  |  |         var client = _httpClientFactory.CreateClient("ElectoralApiClient"); | 
					
						
							| 
									
										
										
										
											2025-08-16 13:30:05 -03:00
										 |  |  |         var requestUri = $"/api/resultados/getTelegramasTotalizados?distritoId={distritoId}&seccionId={seccionId}"; | 
					
						
							| 
									
										
										
										
											2025-08-18 17:47:11 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  |         if (categoriaId.HasValue) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             requestUri += $"&categoriaId={categoriaId.Value}"; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-08-15 17:31:51 -03:00
										 |  |  |         var request = new HttpRequestMessage(HttpMethod.Get, requestUri); | 
					
						
							|  |  |  |         request.Headers.Add("Authorization", $"Bearer {authToken}"); | 
					
						
							|  |  |  |         var response = await client.SendAsync(request); | 
					
						
							| 
									
										
										
										
											2025-08-19 14:07:19 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  |         // Ahora deserializamos al tipo correcto: List<string> | 
					
						
							|  |  |  |         return response.IsSuccessStatusCode ? await response.Content.ReadFromJsonAsync<List<string>>() : null; | 
					
						
							| 
									
										
										
										
											2025-08-15 17:31:51 -03:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     public async Task<TelegramaFileDto?> GetTelegramaFileAsync(string authToken, string mesaId) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         var client = _httpClientFactory.CreateClient("ElectoralApiClient"); | 
					
						
							| 
									
										
										
										
											2025-08-16 13:30:05 -03:00
										 |  |  |         var requestUri = $"/api/resultados/getFile?mesaId={mesaId}"; | 
					
						
							| 
									
										
										
										
											2025-08-15 17:31:51 -03:00
										 |  |  |         var request = new HttpRequestMessage(HttpMethod.Get, requestUri); | 
					
						
							|  |  |  |         request.Headers.Add("Authorization", $"Bearer {authToken}"); | 
					
						
							| 
									
										
										
										
											2025-08-19 14:23:51 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  |         HttpResponseMessage response; | 
					
						
							|  |  |  |         try | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             response = await client.SendAsync(request); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         catch (Exception ex) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             _logger.LogError(ex, "La petición HTTP a getFile falló para la mesa {mesaId}", mesaId); | 
					
						
							|  |  |  |             return null; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (response.IsSuccessStatusCode && response.Content?.Headers.ContentLength > 0) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             try | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |                 return await response.Content.ReadFromJsonAsync<TelegramaFileDto>(); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             catch (JsonException ex) | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |                 // Si la deserialización falla, ahora lo sabremos exactamente. | 
					
						
							|  |  |  |                 _logger.LogWarning(ex, "La API devolvió una respuesta no-JSON para la mesa {mesaId}. Status: {statusCode}", mesaId, response.StatusCode); | 
					
						
							|  |  |  |                 return null; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         else if (!response.IsSuccessStatusCode) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             _logger.LogWarning("La API devolvió un código de error {statusCode} para la mesa {mesaId}", response.StatusCode, mesaId); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         // Si la respuesta fue exitosa pero sin contenido, no es necesario loguearlo como un error, | 
					
						
							|  |  |  |         // simplemente devolvemos null y el Worker lo ignorará. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return null; | 
					
						
							| 
									
										
										
										
											2025-08-15 17:31:51 -03:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2025-08-14 15:27:45 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-08-15 17:31:51 -03:00
										 |  |  |     public async Task<ResumenDto?> GetResumenAsync(string authToken, string distritoId) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         var client = _httpClientFactory.CreateClient("ElectoralApiClient"); | 
					
						
							| 
									
										
										
										
											2025-08-16 13:30:05 -03:00
										 |  |  |         var requestUri = $"/api/resultados/getResumen?distritoId={distritoId}"; | 
					
						
							| 
									
										
										
										
											2025-08-15 17:31:51 -03:00
										 |  |  |         var request = new HttpRequestMessage(HttpMethod.Get, requestUri); | 
					
						
							|  |  |  |         request.Headers.Add("Authorization", $"Bearer {authToken}"); | 
					
						
							|  |  |  |         var response = await client.SendAsync(request); | 
					
						
							|  |  |  |         return response.IsSuccessStatusCode ? await response.Content.ReadFromJsonAsync<ResumenDto>() : null; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2025-08-14 15:27:45 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-08-17 20:08:38 -03:00
										 |  |  |     public async Task<EstadoRecuentoGeneralDto?> GetEstadoRecuentoGeneralAsync(string authToken, string distritoId, int categoriaId) | 
					
						
							| 
									
										
										
										
											2025-08-15 17:31:51 -03:00
										 |  |  |     { | 
					
						
							|  |  |  |         var client = _httpClientFactory.CreateClient("ElectoralApiClient"); | 
					
						
							| 
									
										
										
										
											2025-08-17 20:08:38 -03:00
										 |  |  |         // La URL ahora usa el parámetro 'categoriaId' que se recibe | 
					
						
							|  |  |  |         var requestUri = $"/api/estados/estadoRecuento?distritoId={distritoId}&categoriaId={categoriaId}"; | 
					
						
							| 
									
										
										
										
											2025-08-15 17:31:51 -03:00
										 |  |  |         var request = new HttpRequestMessage(HttpMethod.Get, requestUri); | 
					
						
							|  |  |  |         request.Headers.Add("Authorization", $"Bearer {authToken}"); | 
					
						
							|  |  |  |         var response = await client.SendAsync(request); | 
					
						
							|  |  |  |         return response.IsSuccessStatusCode ? await response.Content.ReadFromJsonAsync<EstadoRecuentoGeneralDto>() : null; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     public async Task<List<CategoriaDto>?> GetCategoriasAsync(string authToken) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         var client = _httpClientFactory.CreateClient("ElectoralApiClient"); | 
					
						
							|  |  |  |         var request = new HttpRequestMessage(HttpMethod.Get, "/api/catalogo/getCategorias"); | 
					
						
							|  |  |  |         request.Headers.Add("Authorization", $"Bearer {authToken}"); | 
					
						
							|  |  |  |         var response = await client.SendAsync(request); | 
					
						
							| 
									
										
										
										
											2025-08-16 11:39:15 -03:00
										 |  |  |         return response.IsSuccessStatusCode ? await response.Content.ReadFromJsonAsync<List<CategoriaDto>>() : null; | 
					
						
							| 
									
										
										
										
											2025-08-14 15:27:45 -03:00
										 |  |  |     } | 
					
						
							|  |  |  | } |