/**
 * CRDT-native bonding curve — pure math functions for $MYCO ↔ cUSDC swaps.
 *
 * Polynomial curve: price = basePrice + coefficient × supply²
 * Ported from payment-infra/services/bonding-curve-service for CRDT ledger integration.
 *
 * All amounts in base units:
 *   - cUSDC: 6 decimals (1_000_000 = $1.00)
 *   - $MYCO: 6 decimals (using 6 effective decimals same as cUSDC for simplicity)
 */

// ── Curve parameters ──

/** Base price in cUSDC units (6 decimals) — $0.01 */
const BASE_PRICE = 10_000;

/** Coefficient — controls curve steepness */
const COEFFICIENT = 0.000001;

/** Exponent — quadratic curve */
const EXPONENT = 2;

/** Sell fee in basis points (0.5% = 50 bps) */
const SELL_FEE_BPS = 50;

// ── Price functions ──

/** Calculate token price at a given supply (both in base units). Returns cUSDC base units per MYCO. */
export function calculatePrice(supplyBaseUnits: number): number {
	const supplyTokens = supplyBaseUnits / 1_000_000;
	return Math.round(BASE_PRICE + COEFFICIENT * Math.pow(supplyTokens, EXPONENT) * 1_000_000);
}

/** Calculate tokens received for cUSDC input (buy). */
export function calculateBuyReturn(cUSDCAmount: number, currentSupply: number): {
	tokensOut: number;
	averagePrice: number;
	priceImpact: number;
	endPrice: number;
} {
	const startPrice = calculatePrice(currentSupply);

	// First estimate with start price
	const estimatedTokens = Math.floor((cUSDCAmount * 1_000_000) / startPrice);
	const endPrice = calculatePrice(currentSupply + estimatedTokens);
	const averagePrice = Math.round((startPrice + endPrice) / 2);

	// Recalculate with average price
	const tokensOut = Math.floor((cUSDCAmount * 1_000_000) / averagePrice);

	// Price impact as percentage (0-100)
	const priceImpact = startPrice > 0
		? Number(((endPrice - startPrice) / startPrice * 100).toFixed(2))
		: 0;

	return { tokensOut, averagePrice, priceImpact, endPrice };
}

/** Calculate cUSDC received for $MYCO input (sell), after fee. */
export function calculateSellReturn(mycoAmount: number, currentSupply: number): {
	cUSDCOut: number;
	grossAmount: number;
	fee: number;
	averagePrice: number;
	priceImpact: number;
	endPrice: number;
} {
	if (mycoAmount > currentSupply) {
		throw new Error('Cannot sell more than current supply');
	}

	const startPrice = calculatePrice(currentSupply);
	const endPrice = calculatePrice(currentSupply - mycoAmount);
	const averagePrice = Math.round((startPrice + endPrice) / 2);

	const grossAmount = Math.floor((mycoAmount * averagePrice) / 1_000_000);
	const fee = Math.floor((grossAmount * SELL_FEE_BPS) / 10_000);
	const cUSDCOut = grossAmount - fee;

	const priceImpact = startPrice > 0
		? Number(((startPrice - endPrice) / startPrice * 100).toFixed(2))
		: 0;

	return { cUSDCOut, grossAmount, fee, averagePrice, priceImpact, endPrice };
}

/** Get current curve configuration (for UI display). */
export function getCurveConfig() {
	return {
		basePrice: BASE_PRICE,
		coefficient: COEFFICIENT,
		exponent: EXPONENT,
		sellFeeBps: SELL_FEE_BPS,
		priceDecimals: 6,
		tokenDecimals: 6,
	};
}
