import { CardConfig, GlobalConfig, VendorState, CalculationResult } from '../types'; /** * Cross-border payment calculation engine. * * ─── PATH A: CASH ───────────────────────────────────────────────────────── * IDR input: Step 1: IDR → USD via bcaBeli (Bali money changer) * Step 2: USD → VND via cashVndUsd (your purchase cost in VN) * USD input: USD → VND via cashVndUsd * * ─── PATH B: CARD (Online / POS) ───────────────────────────────────────── * IDR input: IDR × card.networkRate (final rate incl. fees) * USD input: USD × card.usdRate (final rate incl. fees) */ export const calculateCosts = ( vendor: VendorState, global: GlobalConfig, activeCard: CardConfig ): CalculationResult => { const price = parseFloat(vendor.price.replace(/[^\d.]/g, '')) || 0; if (!price) { return { usdNeeded: 0, cashVnd: 0, onlineVnd: 0, posVnd: 0, isCashPossible: false, formulas: { cash: '', online: '', pos: '' } }; } // ── Inputs ─────────────────────────────────────────────────────────────── const IDR_PER_USD = global.bcaBeli || 16000; // Bali rate (CASH ONLY) const CASH_USD_VND = global.cashVndUsd || 26000; // Cash baseline // High-precision rates might come as strings from the UI const CARD_IDR_VND = typeof activeCard.networkRate === 'string' ? (parseFloat(activeCard.networkRate) || 0) : (activeCard.networkRate || 1.58); const CARD_USD_VND = typeof activeCard.usdRate === 'string' ? (parseFloat(activeCard.usdRate) || 0) : (activeCard.usdRate || 26000); const POS_MULT = vendor.surcharge ? 1.03 : 1; // ── PATH A: CASH ───────────────────────────────────────────────────────── let usdNeeded: number; let cashVnd: number; if (vendor.currency === 'IDR') { usdNeeded = price / IDR_PER_USD; cashVnd = usdNeeded * CASH_USD_VND; } else { usdNeeded = price; cashVnd = price * CASH_USD_VND; } // ── PATH B: CARD ───────────────────────────────────────────────────────── let onlineVnd: number; let posVnd: number; if (vendor.currency === 'IDR') { onlineVnd = price * CARD_IDR_VND; posVnd = price * POS_MULT * CARD_IDR_VND; } else { onlineVnd = price * CARD_USD_VND; posVnd = price * POS_MULT * CARD_USD_VND; } // ── Tooltip strings ─────────────────────────────────────────────────────── let cashFormula: string; let onlineFormula: string; let posFormula: string; if (vendor.currency === 'IDR') { cashFormula = `B1: ${formatNumber(price)} IDR ÷ ${formatNumber(IDR_PER_USD)} (Tỉ giá Bali)\n` + `= $${formatNumber(usdNeeded, 4)}\n` + `B2: $${formatNumber(usdNeeded, 4)} × ${formatVND(CASH_USD_VND)} (Giá vốn)\n` + `= ${formatVND(cashVnd)}`; onlineFormula = `${formatNumber(price)} IDR × ${formatNumber(CARD_IDR_VND, 7)} (Tỉ giá thẻ)\n` + `= ${formatVND(onlineVnd)}`; posFormula = `${formatNumber(price)} IDR` + `${vendor.surcharge ? ' × 1.03 (Phụ phí POS)' : ''} × ${formatNumber(CARD_IDR_VND, 7)}\n` + `= ${formatVND(posVnd)}`; } else { cashFormula = `$${formatNumber(price, 2)} × ${formatVND(CASH_USD_VND)} (Giá vốn USD)\n` + `= ${formatVND(cashVnd)}`; onlineFormula = `$${formatNumber(price, 2)} × ${formatVND(CARD_USD_VND)} (Tỉ giá thẻ)\n` + `= ${formatVND(onlineVnd)}`; posFormula = `$${formatNumber(price, 2)}` + `${vendor.surcharge ? ' × 1.03 (Phụ phí POS)' : ''} × ${formatVND(CARD_USD_VND)}\n` + `= ${formatVND(posVnd)}`; } return { usdNeeded, cashVnd, onlineVnd, posVnd, isCashPossible: usdNeeded <= global.usdAvailable, formulas: { cash: cashFormula, online: onlineFormula, pos: posFormula, } }; }; export const formatVND = (val: number) => { const formatted = new Intl.NumberFormat('en-US', { style: 'decimal', maximumFractionDigits: 0 }).format(Math.round(val)); return `${formatted}đ`; }; export const formatNumber = (val: number | string, decimals = 0) => { const num = typeof val === 'string' ? parseFloat(val.replace(/,/g, '')) : val; if (isNaN(num)) return ''; return new Intl.NumberFormat('en-US', { minimumFractionDigits: decimals, maximumFractionDigits: decimals, }).format(num); };