import {planBudget,riskPresets,type PlanInput,type InvestmentPlan} from './smart-investment';
import {wallexFresh,wallexAssets,type WallexQuote} from './wallex';
import type {Project} from './catalog';
export type WallexPlanAsset=Pick<Project,'id'|'symbol'|'title'>&{wallex:WallexQuote};
export function buildWallexInvestmentPlan(quotes:WallexQuote[],input:PlanInput,now=Date.now()):InvestmentPlan<WallexPlanAsset>{
 const empty=(error:InvestmentPlan['error']):InvestmentPlan<WallexPlanAsset>=>({budgetRial:0,investedRial:0,cashRial:0,cashShareTenths:0,allocations:[],eligibleCount:0,excludedCount:0,error});
 const budget=planBudget(input.amount,input.currency,input.usdtRate);if(budget.rial===null)return empty(budget.error);
 if(!Object.hasOwn(riskPresets,input.risk))return empty('settings');
 const capital=budget.rial,selected=new Set(input.projectIds),seen=new Set<string>();
 const eligible=quotes.filter(q=>{if(seen.has(q.symbol))return false;seen.add(q.symbol);return selected.has(q.symbol)&&wallexFresh(q,now)&&q.spot&&q.amountPrecision!==null&&q.amountPrecision>=0&&q.amountPrecision<=12&&/^\d+(?:\.\d)?$/.test(q.price)&&Number(q.price)>0});
 const base={...empty(selected.size?null:'selection'),budgetRial:Number(capital),cashRial:Number(capital),cashShareTenths:1000,eligibleCount:eligible.length,excludedCount:selected.size-eligible.length};
 if(!eligible.length)return base;
 const policy=riskPresets[input.risk],available=capital*BigInt(100-policy.reservePercent)/BigInt(100),cap=capital*BigInt(policy.maxTokenPercent)/BigInt(100),target=available/BigInt(eligible.length)<cap?available/BigInt(eligible.length):cap;
 const allocations=eligible.flatMap(q=>{
  const [whole,fraction='']=q.price.split('.'),priceRial=BigInt(whole)*BigInt(10)+BigInt(fraction||'0'),factor=BigInt(10)**BigInt(q.amountPrecision!),units=target*factor/priceRial;
  if(!units)return [];
  const spent=(units*priceRial+factor-BigInt(1))/factor;
  const quantity=q.amountPrecision?`${units/factor}.${(units%factor).toString().padStart(q.amountPrecision!,'0')}`.replace(/\.?0+$/,''):units.toString();
  const asset=wallexAssets.find(a=>a.symbol===q.symbol)!;
  return [{project:{id:q.symbol,symbol:q.base,title:{fa:q.name,en:asset.description},wallex:q},units:Number(quantity),quantity,amountRial:Number(spent),shareTenths:Number(spent*BigInt(1000)/capital)}];
 });
 const used=allocations.reduce((sum,a)=>sum+BigInt(a.amountRial),BigInt(0)),cash=capital-used;
 // Allocate display rounding separately from money; percentages always sum to 100%.
 const rows=[...allocations.map(a=>BigInt(a.amountRial)),cash],parts=rows.map(a=>Number(a*BigInt(1000)/capital)),order=rows.map((a,i)=>({i,r:a*BigInt(1000)%capital})).sort((a,b)=>a.r===b.r?a.i-b.i:a.r>b.r?-1:1);
 for(let i=0,left=1000-parts.reduce((a,b)=>a+b,0);i<left;i++)parts[order[i].i]++;
 return {...base,investedRial:Number(used),cashRial:Number(cash),cashShareTenths:parts.at(-1)!,allocations:allocations.map((a,i)=>({...a,shareTenths:parts[i]}))};
}
