import { formatUnits } from 'ethers';
import { isChain138CanonicalLivePool } from '../config/chain138-live-dodo-pools';
import { isChain138CashUsdTokenAddress } from '../config/chain138-cash-tokens';
import { getCanonicalTokenByAddress } from '../config/canonical-tokens';
import type { LiquidityPool } from '../database/repositories/pool-repo';
import { getCanonicalPriceUsd } from './canonical-price-oracle';
import { collectVisiblePools } from './token-visible-liquidity';

const CHAIN_138 = 138;

function normalizeAddress(value: string): string {
  return value.trim().toLowerCase();
}

function decimalsForAddress(address: string): number {
  const spec = getCanonicalTokenByAddress(CHAIN_138, normalizeAddress(address));
  return Number(spec?.decimals ?? 18);
}

function parseReserveAmountForToken(raw: string | undefined, tokenAddress: string): number {
  if (!raw || raw.trim() === '') return 0;
  try {
    const value = BigInt(raw);
    if (value <= 0n) return 0;
    const parsed = Number(formatUnits(value, decimalsForAddress(tokenAddress)));
    return Number.isFinite(parsed) && parsed > 0 ? parsed : 0;
  } catch {
    return 0;
  }
}

/** USD value of cash-token legs only (policy peg), excluding cBTC/WETH/XAU pool sides. */
export function cashLiquidityUsdFromPool(pool: LiquidityPool): number {
  if (pool.chainId !== CHAIN_138) return 0;

  let total = 0;
  const legs = [
    { address: pool.token0Address, reserve: pool.reserve0 },
    { address: pool.token1Address, reserve: pool.reserve1 },
  ];

  for (const leg of legs) {
    const address = normalizeAddress(leg.address);
    if (!isChain138CashUsdTokenAddress(address)) continue;
    const amount = parseReserveAmountForToken(leg.reserve, address);
    if (amount <= 0) continue;
    const priceUsd = getCanonicalPriceUsd(CHAIN_138, address) ?? 1;
    total += amount * priceUsd;
  }

  return total;
}

/**
 * Total USD cash sitting in canonical Stack A PMM pools that include this token.
 * Counts only cUSDC/cUSDT/USDC/USDT mirror legs at the GRU cash peg — not full DEX pool TVL.
 */
export async function resolveTokenCashLiquidityUsd(chainId: number, address: string): Promise<number> {
  if (chainId !== CHAIN_138) return 0;

  const normalized = normalizeAddress(address);
  const pools = await collectVisiblePools(chainId, normalized);
  const canonicalPools = pools.filter((pool) => isChain138CanonicalLivePool(pool.poolAddress));
  const scopedPools = canonicalPools.length > 0 ? canonicalPools : pools;

  return scopedPools.reduce((sum, pool) => sum + cashLiquidityUsdFromPool(pool), 0);
}
