using Mercados.Core.Entities; using Mercados.Infrastructure.Persistence.Repositories; using Mercados.Infrastructure.Services; using Microsoft.AspNetCore.Mvc; namespace Mercados.Api.Controllers { [ApiController] [Route("api/[controller]")] public class MercadosController : ControllerBase { private readonly ICotizacionBolsaRepository _bolsaRepo; private readonly ICotizacionGranoRepository _granoRepo; private readonly ICotizacionGanadoRepository _ganadoRepo; private readonly IHolidayService _holidayService; private readonly ILogger _logger; // Inyectamos TODOS los repositorios que necesita el controlador. public MercadosController( ICotizacionBolsaRepository bolsaRepo, ICotizacionGranoRepository granoRepo, ICotizacionGanadoRepository ganadoRepo, IHolidayService holidayService, ILogger logger) { _bolsaRepo = bolsaRepo; _granoRepo = granoRepo; _ganadoRepo = ganadoRepo; _holidayService = holidayService; _logger = logger; } // --- Endpoint para Agroganadero --- [HttpGet("agroganadero")] [ProducesResponseType(typeof(IEnumerable), StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status500InternalServerError)] public async Task GetAgroganadero() { try { var hoy = DateOnly.FromDateTime(DateTime.UtcNow); var data = await _ganadoRepo.ObtenerTandaPorFechaAsync(hoy); return Ok(data); } catch (Exception ex) { _logger.LogError(ex, "Error al obtener cotizaciones de agroganadero."); return StatusCode(500, "Ocurrió un error interno en el servidor."); } } // --- Endpoint para Granos --- [HttpGet("granos")] [ProducesResponseType(typeof(IEnumerable), StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status500InternalServerError)] public async Task GetGranos() { try { var data = await _granoRepo.ObtenerUltimasAsync(); return Ok(data); } catch (Exception ex) { _logger.LogError(ex, "Error al obtener cotizaciones de granos."); return StatusCode(500, "Ocurrió un error interno en el servidor."); } } // --- Endpoints de Bolsa --- [HttpGet("bolsa/eeuu")] [ProducesResponseType(typeof(IEnumerable), StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status500InternalServerError)] public async Task GetBolsaUsa() { try { var data = await _bolsaRepo.ObtenerUltimasPorMercadoAsync("EEUU"); return Ok(data); } catch (Exception ex) { _logger.LogError(ex, "Error al obtener cotizaciones de bolsa de EEUU."); return StatusCode(500, "Ocurrió un error interno en el servidor."); } } [HttpGet("bolsa/local")] [ProducesResponseType(typeof(IEnumerable), StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status500InternalServerError)] public async Task GetBolsaLocal() { try { var data = await _bolsaRepo.ObtenerUltimasPorMercadoAsync("Local"); return Ok(data); } catch (Exception ex) { _logger.LogError(ex, "Error al obtener cotizaciones de bolsa local."); return StatusCode(500, "Ocurrió un error interno en el servidor."); } } [HttpGet("bolsa/history/{ticker}")] [ProducesResponseType(typeof(IEnumerable), StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status500InternalServerError)] public async Task GetBolsaHistory(string ticker, [FromQuery] string mercado = "Local", [FromQuery] int dias = 30) { try { var data = await _bolsaRepo.ObtenerHistorialPorTickerAsync(ticker, mercado, dias); return Ok(data); } catch (Exception ex) { _logger.LogError(ex, "Error al obtener historial para el ticker {Ticker}.", ticker); return StatusCode(500, "Ocurrió un error interno en el servidor."); } } [HttpGet("agroganadero/history")] [ProducesResponseType(typeof(IEnumerable), StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status500InternalServerError)] public async Task GetAgroganaderoHistory([FromQuery] string categoria, [FromQuery] string especificaciones, [FromQuery] int dias = 30) { try { var data = await _ganadoRepo.ObtenerHistorialAsync(categoria, especificaciones, dias); return Ok(data); } catch (Exception ex) { _logger.LogError(ex, "Error al obtener historial para la categoría {Categoria}.", categoria); return StatusCode(500, "Ocurrió un error interno en el servidor."); } } [HttpGet("granos/history/{nombre}")] [ProducesResponseType(typeof(IEnumerable), StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status500InternalServerError)] public async Task GetGranoHistory(string nombre, [FromQuery] int dias = 30) { try { var data = await _granoRepo.ObtenerHistorialAsync(nombre, dias); return Ok(data); } catch (Exception ex) { _logger.LogError(ex, "Error al obtener historial para el grano {Grano}.", nombre); return StatusCode(500, "Ocurrió un error interno en el servidor."); } } [HttpGet("es-feriado/{mercado}")] [ProducesResponseType(typeof(bool), StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status500InternalServerError)] public async Task IsMarketHoliday(string mercado) { try { // Usamos la fecha actual en la zona horaria de Argentina TimeZoneInfo argentinaTimeZone; try { argentinaTimeZone = TimeZoneInfo.FindSystemTimeZoneById("America/Argentina/Buenos_Aires"); } catch { argentinaTimeZone = TimeZoneInfo.FindSystemTimeZoneById("Argentina Standard Time"); } var todayInArgentina = TimeZoneInfo.ConvertTimeFromUtc(DateTime.UtcNow, argentinaTimeZone); var esFeriado = await _holidayService.IsMarketHolidayAsync(mercado.ToUpper(), todayInArgentina); return Ok(esFeriado); } catch (Exception ex) { _logger.LogError(ex, "Error al comprobar si es feriado para el mercado {Mercado}.", mercado); // Si hay un error, devolvemos 'false' para no bloquear la UI innecesariamente. return Ok(false); } } } }