package com.paymentlink.service; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import org.springframework.web.client.RestTemplate; import java.util.HashMap; import java.util.Map; @Service public class TaxService { private static final Logger logger = LoggerFactory.getLogger(TaxService.class); @Value("${tax.default.rate:0.08}") private double defaultTaxRate; @Value("${tax.api.url:}") private String taxApiUrl; @Value("${tax.api.timeout:5000}") private int taxApiTimeout; private final Map countryRates = new HashMap<>(); private final Map> stateRates = new HashMap<>(); public TaxService() { initializeTaxRates(); } private void initializeTaxRates() { // Country-specific rates countryRates.put("GB", 0.20); // UK VAT countryRates.put("US", 0.08); // US average countryRates.put("CA", 0.13); // Canada average countryRates.put("AU", 0.10); // Australia GST countryRates.put("DE", 0.19); // Germany VAT countryRates.put("FR", 0.20); // France VAT countryRates.put("IT", 0.22); // Italy VAT countryRates.put("ES", 0.21); // Spain VAT countryRates.put("NL", 0.21); // Netherlands VAT countryRates.put("BE", 0.21); // Belgium VAT // US State-specific rates Map usStates = new HashMap<>(); usStates.put("CA", 0.1025); // California usStates.put("NY", 0.08); // New York usStates.put("TX", 0.0825); // Texas usStates.put("FL", 0.06); // Florida usStates.put("WA", 0.101); // Washington stateRates.put("US", usStates); // Canadian Province-specific rates Map caProvinces = new HashMap<>(); caProvinces.put("ON", 0.13); // Ontario HST caProvinces.put("BC", 0.12); // British Columbia caProvinces.put("QC", 0.14975); // Quebec stateRates.put("CA", caProvinces); } /** * Calculate tax amount for a subtotal */ public long calculateTax(long subtotal, String country, String state) { double rate = getTaxRate(country, state); long taxAmount = Math.round(subtotal * rate); logger.debug("Calculated tax: subtotal={}, country={}, state={}, rate={}, tax={}", subtotal, country, state, rate, taxAmount); return taxAmount; } /** * Get tax rate for country/state */ public double getTaxRate(String country, String state) { // Try external API first if configured if (taxApiUrl != null && !taxApiUrl.isEmpty()) { try { Double apiRate = fetchTaxRateFromApi(country, state); if (apiRate != null) { return apiRate; } } catch (Exception e) { logger.warn("Failed to fetch tax rate from API, using local rates", e); } } // Try state-specific rate if (state != null && !state.isEmpty() && stateRates.containsKey(country)) { Map states = stateRates.get(country); if (states.containsKey(state)) { return states.get(state); } } // Try country rate if (country != null && countryRates.containsKey(country)) { return countryRates.get(country); } // Return default return defaultTaxRate; } /** * Fetch tax rate from external API */ private Double fetchTaxRateFromApi(String country, String state) { try { RestTemplate restTemplate = new RestTemplate(); String url = taxApiUrl + "?country=" + country + "&state=" + (state != null ? state : ""); @SuppressWarnings("unchecked") Map response = restTemplate.getForObject(url, Map.class); if (response != null) { // Try "taxRate" field if (response.containsKey("taxRate")) { return ((Number) response.get("taxRate")).doubleValue(); } // Try "rate" field if (response.containsKey("rate")) { return ((Number) response.get("rate")).doubleValue(); } } } catch (Exception e) { logger.error("Error fetching tax rate from API", e); } return null; } /** * Get all supported countries */ public Map getSupportedCountries() { Map countries = new HashMap<>(); countries.put("US", "United States"); countries.put("CA", "Canada"); countries.put("GB", "United Kingdom"); countries.put("AU", "Australia"); countries.put("DE", "Germany"); countries.put("FR", "France"); countries.put("IT", "Italy"); countries.put("ES", "Spain"); countries.put("NL", "Netherlands"); countries.put("BE", "Belgium"); return countries; } }