using Microsoft.AspNetCore.Mvc; using Documents.Models; using Domain.Dtos; using Domain.Entities; using Domain.Generics; using Models.Interfaces; using System.Reflection; using Documents.Interfaces; namespace phronCare.API.Controllers.Sales { [Route("api/[controller]")] [ApiController] public class QuoteController : ControllerBase { private readonly IDocumentTemplateService _documentTemplateService; private readonly IQuoteDom _quoteService; public QuoteController(IDocumentTemplateService documentTemplateService, IQuoteDom quoteService) { _documentTemplateService = documentTemplateService ?? throw new ArgumentNullException(nameof(documentTemplateService)); ; _quoteService = quoteService ?? throw new ArgumentNullException(nameof(quoteService)); } #region Obtener Presupuestos /// /// Busca presupuestos con filtros de texto libre o por ID, paginados. /// [HttpGet("search")] public async Task>> Search( [FromQuery] int? customerId, [FromQuery] string? customerText, [FromQuery] string? quoteNumber, [FromQuery] int? professionalId, [FromQuery] string? professionalText, [FromQuery] int? institutionId, [FromQuery] string? institutionText, [FromQuery] int? patientId, [FromQuery] string? patientText, [FromQuery] DateTime? issueDateFrom, [FromQuery] DateTime? issueDateTo, [FromQuery] string? status, [FromQuery] int page = 1, [FromQuery] int pageSize = 50) { try { var result = await _quoteService.SearchAsync( customerId, customerText, quoteNumber, professionalId, professionalText, institutionId, institutionText, patientId, patientText, issueDateFrom, issueDateTo, status, page, pageSize); return Ok(result); } catch (Exception ex) { var methodName = MethodBase.GetCurrentMethod()?.Name ?? "UnknownMethod"; // Log exception as needed... return StatusCode(500, $"{methodName} Message: {ex.Message}"); } } [HttpGet("{id}/pdf")] public async Task GetQuotePdf(int id) { var quote = await _quoteService.GetDtoByIdAsync(id); if (quote == null) return NotFound($"Presupuesto con ID {id} no encontrado."); var pdfBytes = await _documentTemplateService.GenerateDocumentAsync(new DocumentGenerationRequest { Model = quote }); return File(pdfBytes, "application/pdf", $"Presupuesto_{quote.Quotenumber}.pdf"); } #endregion #region Endpoint de emision de presupuesto (encabezado + detalles + roles + ajustes + impuestos) [HttpPost("createfull")] public async Task CreateFullQuote([FromBody] CreateFullQuoteRequest request) { try { // Validamos que el request y el objeto Quote no sean nulos if (request == null || request.Quote == null) return BadRequest("El payload no puede contener elementos nulos."); // Desempaquetamos los datos var quote = request.Quote; var formSeriesId = request.FormSeriesId; // Llamada al servicio de negocio var quoteNumber = await _quoteService.CreateFullQuoteAsync(quote, formSeriesId); // Devolvemos el número generado return Ok(new { Success = true, QuoteNumber = quoteNumber }); } catch (ArgumentNullException ex) { return BadRequest($"Validación fallida: {ex.Message}"); } catch (InvalidOperationException ex) { return BadRequest($"Error de negocio: {ex.Message}"); } catch (Exception ex) { return StatusCode(500, $"Ocurrió un error interno: {ex.Message}"); } } public class CreateFullQuoteRequest { public EQuoteHeader Quote { get; set; } = default!; public int FormSeriesId { get; set; } } #endregion } }