package com.imprimelibros.erp.externalApi; import org.springframework.beans.factory.annotation.Value; import org.springframework.http.*; import org.springframework.stereotype.Service; import org.springframework.web.client.HttpClientErrorException; import org.springframework.web.client.RestTemplate; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.JsonNode; import com.imprimelibros.erp.configuracion.margenes_presupuestos.MargenPresupuesto; import com.imprimelibros.erp.configuracion.margenes_presupuestos.MargenPresupuestoDao; import com.imprimelibros.erp.presupuesto.dto.Presupuesto.TipoCubierta; import com.imprimelibros.erp.presupuesto.dto.Presupuesto.TipoEncuadernacion; import java.util.Map; import java.util.HashMap; import java.util.List; import java.util.function.Supplier; @Service public class skApiClient { @Value("${safekat.api.url}") private String skApiUrl; private final AuthService authService; private final RestTemplate restTemplate; private final MargenPresupuestoDao margenPresupuestoDao; public skApiClient(AuthService authService, MargenPresupuestoDao margenPresupuestoDao) { this.authService = authService; this.restTemplate = new RestTemplate(); this.margenPresupuestoDao = margenPresupuestoDao; } public String getPrice(Map requestBody, TipoEncuadernacion tipoEncuadernacion, TipoCubierta tipoCubierta) { return performWithRetry(() -> { String url = this.skApiUrl + "api/calcular"; HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_JSON); headers.setBearerAuth(authService.getToken()); HttpEntity> entity = new HttpEntity<>(requestBody, headers); ResponseEntity response = restTemplate.exchange( url, HttpMethod.POST, entity, String.class); try { Map responseBody = new ObjectMapper().readValue( response.getBody(), new TypeReference>() { }); ObjectMapper mapper = new ObjectMapper(); if (responseBody.get("error") == null) { Object dataObj = responseBody.get("data"); if (dataObj instanceof Map) { @SuppressWarnings("unchecked") Map data = (Map) dataObj; List tiradas = mapper.convertValue( data.get("tiradas"), new TypeReference>() { }); List precios = mapper.convertValue( data.get("precios"), new TypeReference>() { }); for (int i = 0; i < tiradas.size(); i++) { int tirada = tiradas.get(i); MargenPresupuesto margen = margenPresupuestoDao.findByTipoAndTirada( tipoEncuadernacion, tipoCubierta, tirada); if (margen != null) { double margenValue = calcularMargen( tirada, margen.getTiradaMin(), margen.getTiradaMax(), margen.getMargenMax(), margen.getMargenMin()); double nuevoPrecio = precios.get(i) * (1 + margenValue / 100.0); precios.set(i, Math.round(nuevoPrecio * 10000.0) / 10000.0); // redondear a 2 decimales } else { System.out.println("No se encontró margen para tirada " + tirada); } } // <-- Clave: sustituir la lista en el map que se devuelve data.put("precios", precios); // (tiradas no cambia, pero si la modificases: data.put("tiradas", tiradas);) } return mapper.writeValueAsString(Map.of("data", responseBody.get("data"))); } else { return "{\"error\": 1}"; } } catch (JsonProcessingException e) { e.printStackTrace(); return "{\"error\": 1}"; } }); } public Integer getMaxSolapas(Map requestBody) { try { String jsonResponse = performWithRetry(() -> { String url = this.skApiUrl + "api/calcular-solapas"; HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_JSON); headers.setBearerAuth(authService.getToken()); // token actualizado Map data = new HashMap<>(); data.put("clienteId", requestBody.get("clienteId")); data.put("tamanio", requestBody.get("tamanio")); data.put("tirada", requestBody.get("tirada")); data.put("paginas", requestBody.get("paginas")); data.put("paginasColor", requestBody.get("paginasColor")); data.put("papelInteriorDiferente", 0); data.put("paginasCuadernillo", requestBody.get("paginasCuadernillo")); data.put("tipo", requestBody.get("tipo")); data.put("isColor", requestBody.get("isColor")); data.put("isHq", requestBody.get("isHq")); data.put("interior", requestBody.get("interior")); HttpEntity> entity = new HttpEntity<>(data, headers); ResponseEntity response = restTemplate.exchange( url, HttpMethod.POST, entity, String.class); return response.getBody(); }); ObjectMapper mapper = new ObjectMapper(); JsonNode root = mapper.readTree(jsonResponse); if (root.get("data") == null || !root.get("data").isInt()) { throw new RuntimeException("Respuesta inesperada de calcular-solapas: " + jsonResponse); } return root.get("data").asInt(); } catch (JsonProcessingException e) { // Fallback al 80% del ancho Map tamanio = new ObjectMapper().convertValue( requestBody.get("tamanio"), new TypeReference>() { }); if (tamanio == null || tamanio.get("ancho") == null) throw new RuntimeException("Tamaño no válido en la solicitud: " + requestBody); else { int ancho = (int) tamanio.get("ancho"); return (int) Math.floor(ancho * 0.8); // 80% del ancho } } } public Double getRetractilado(Map requestBody) { String value = performWithRetry(() -> { String url = this.skApiUrl + "api/calcular-retractilado"; HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_JSON); headers.setBearerAuth(authService.getToken()); HttpEntity> entity = new HttpEntity<>(requestBody, headers); ResponseEntity response = restTemplate.exchange( url, HttpMethod.POST, entity, String.class); try { Map responseBody = new ObjectMapper().readValue( response.getBody(), new TypeReference>() { }); return responseBody.get("data").toString(); } catch (JsonProcessingException e) { e.printStackTrace(); return "0.0"; // Fallback en caso de error } }); try { return Double.parseDouble(value); } catch (NumberFormatException e) { throw new RuntimeException("Error al parsear el valor de retractilado: " + value, e); } } /****************** * PRIVATE METHODS ******************/ private String performWithRetry(Supplier request) { try { return request.get(); } catch (HttpClientErrorException.Unauthorized e) { // Token expirado, renovar y reintentar authService.invalidateToken(); try { return request.get(); // segundo intento } catch (HttpClientErrorException ex) { throw new RuntimeException("La autenticación ha fallado tras renovar el token.", ex); } } } private static double calcularMargen( int tirada, int tiradaMin, int tiradaMax, double margenMax, double margenMin) { if (tirada <= tiradaMin) return margenMax; if (tirada >= tiradaMax) return margenMin; return margenMax - ((double) (tirada - tiradaMin) / (tiradaMax - tiradaMin)) * (margenMax - margenMin); } }