import type {DashboardData} from './dashboard';

export type TradeSide='buy'|'sell';
export const TOKEN_SCALE=BigInt(10)**BigInt(18);
const MAX_AMOUNT=BigInt(Number.MAX_SAFE_INTEGER);
function normalize(value:string){return value.replace(/[۰-۹]/g,d=>String('۰۱۲۳۴۵۶۷۸۹'.indexOf(d))).replace(/[٠-٩]/g,d=>String('٠١٢٣٤٥٦٧٨٩'.indexOf(d))).replace(/[,٬\s]/g,'').replace(/٫/g,'.')}
function decimal(value:string,scale:number):bigint|null{
 if(value.length>100)return null;
 const input=normalize(value);
 if(!/^\d+(?:\.\d+)?$/.test(input))return null;
 const [whole,fraction='']=input.split('.');
 if(fraction.length>scale)return null;
 return BigInt(whole)*BigInt(10)**BigInt(scale)+BigInt(fraction.padEnd(scale,'0')||'0');
}
export type TradeCalculation={units:bigint;grossRial:bigint;unusedRial:bigint;error:'amount'|'minimum'|'range'|null};
// Quotes are estimates in whole project tokens. No balances or orders are mutated.
export function calculateTrade(input:string,side:TradeSide,unitPriceRial:number):TradeCalculation{
 const empty=(error:TradeCalculation['error']):TradeCalculation=>({units:BigInt(0),grossRial:BigInt(0),unusedRial:BigInt(0),error});
 if(!Number.isSafeInteger(unitPriceRial)||unitPriceRial<=0)return empty('range');
 const value=decimal(input,side==='buy'?1:0);
 if(value===null||value<=BigInt(0))return empty('amount');
 if(value>MAX_AMOUNT)return empty('range');
 const price=BigInt(unitPriceRial),units=side==='buy'?value/price:value,grossRial=units*price;
 if(units===BigInt(0))return empty('minimum');
 if(grossRial>MAX_AMOUNT)return empty('range');
 return {units,grossRial,unusedRial:side==='buy'?value-grossRial:BigInt(0),error:null};
}
export function rialToToman(value:bigint){return (value/BigInt(10)).toString()+(value%BigInt(10)?'.'+(value%BigInt(10)).toString():'')}
export function tokenDecimal(value:bigint){const fraction=(value%TOKEN_SCALE).toString().padStart(18,'0').replace(/0+$/,'');return (value/TOKEN_SCALE).toString()+(fraction?'.'+fraction:'')}
export function availableTradeBalances(positions:DashboardData['positions'],projectId:string){
 let cashAtomic=BigInt(0),tokenAtomic=BigInt(0),cashValid=true,tokenValid=true;
 for(const row of positions){
  const cash=row.project_id===null&&(row.asset_symbol==='TMN'||row.asset_symbol==='IRR'),token=row.project_id===projectId;
  if(!cash&&!token)continue;
  const total=decimal(row.quantity,18),locked=decimal(row.locked_quantity,18);
  if(total===null||locked===null||locked>total){if(cash)cashValid=false;if(token)tokenValid=false;continue}
  const available=total-locked;
  if(cash)cashAtomic+=available*(row.asset_symbol==='TMN'?BigInt(10):BigInt(1));
  if(token)tokenAtomic+=available;
 }
 return {cashRial:cashValid?cashAtomic/TOKEN_SCALE:null,tokenAtomic:tokenValid?tokenAtomic:null};
}
export function maxTradeInput(side:TradeSide,cashRial:bigint|null,tokenAtomic:bigint|null,unitPriceRial:number,remainingUnits:number){
 if(!Number.isSafeInteger(unitPriceRial)||unitPriceRial<=0||!Number.isSafeInteger(remainingUnits))return '';
 if(side==='sell')return tokenAtomic===null?'':(tokenAtomic/TOKEN_SCALE).toString();
 if(cashRial===null)return '';
 const capacity=BigInt(Math.max(0,remainingUnits))*BigInt(unitPriceRial);
 return rialToToman(cashRial<capacity?cashRial:capacity);
}
