(function(root,factory){const api=factory(typeof module==='object'&&module.exports?require('./tools-core.js'):root.LwTools);if(typeof module==='object'&&module.exports)module.exports=api;else root.LwPortfolioFx=api;})(typeof globalThis!=='undefined'?globalThis:this,T=>{
'use strict';const currencies=['USD','EUR','GBP','PLN'];
function transaction(row,index=0){
 const tx=T.transaction(row,index),currency=row.currency??'USD';if(!currencies.includes(currency))throw Error('Supported transaction currencies: USD, EUR, GBP and PLN.');
 const rates={USD:1};if(row.fx!==undefined){if(!row.fx||typeof row.fx!=='object'||Array.isArray(row.fx))throw Error('Invalid historical FX.');for(const key of currencies){if(row.fx[key]===undefined||row.fx[key]===null||row.fx[key]==='')continue;const value=T.number(row.fx[key],'historical '+key+' rate',1e6);if(value<1e-9||key==='USD'&&value!==1)throw Error('Historical FX must be positive, with USD equal to 1.');rates[key]=value;}}
 if(!rates[currency])throw Error('Enter the historical '+currency+' per USD exchange rate.');
 const fxDate=row.fxDate?T.date(row.fxDate):null;if(fxDate&&fxDate>tx.date)throw Error('The FX source date cannot be later than the transaction.');
 if(Object.keys(rates).length>1&&!fxDate)throw Error('Record the date of the historical FX rates.');
 const fxSource=row.fxSource??'USD only';if(!['USD only','Manual','ECB reference'].includes(fxSource))throw Error('Unknown FX source.');
 if(fxSource==='ECB reference'&&(!fxDate||Date.parse(tx.date)-Date.parse(fxDate)>7*86400000))throw Error('ECB reference must be dated within seven days of the transaction.');
 return {...tx,currency,fx:rates,fxDate,fxSource};
}
function convert(row,target){const rate=row.fx[target]/row.fx[row.currency];if(!Number.isFinite(rate)||rate<=0)throw Error('Historical '+target+' rates are missing. Add them to the affected transactions.');return {...row,price:row.price*rate,fee:row.fee*rate};}
function usdRows(rows){return rows.map((r,i)=>convert(transaction(r,i),'USD'));}
function ledger(rows,target,currentPrice=null,usdPrice=null){
 if(!currencies.includes(target))throw Error('Invalid summary currency.');const normalized=rows.map((r,i)=>transaction(r,i));
 const result=T.ledger(normalized.map(r=>convert(r,target)),currentPrice);
 let attribution=null;
 if(Number.isFinite(currentPrice)&&currentPrice>0&&Number.isFinite(usdPrice)&&usdPrice>0){
  const currentFx=currentPrice/usdPrice,grossUSD=T.ledger(usdRows(normalized).map(r=>({...r,fee:0})),usdPrice).total;
  const ltc=grossUSD*currentFx,fees=-result.fees,fx=result.total-ltc-fees;
  attribution={ltc,fx:target==='USD'?0:fx,fees,total:result.total};
 }
 return {...result,attribution};
}
function fingerprint(r){return JSON.stringify([r.type,r.date,r.amount,r.currency,r.price,r.fee,r.notes]);}
function merge(existing,incoming){
 const count=new Map();existing.map((r,i)=>transaction(r,i)).forEach(r=>count.set(fingerprint(r),(count.get(fingerprint(r))||0)+1));const added=[];let duplicates=0;
 incoming.map((r,i)=>transaction(r,i)).forEach(r=>{const key=fingerprint(r),n=count.get(key)||0;if(n){count.set(key,n-1);duplicates++;}else added.push(r);});return {added,duplicates};
}
return {currencies,transaction,usdRows,ledger,merge};
});
