// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity ^0.8.19;

import "@uniswap-v3-core/interfaces/IUniswapV3Factory.sol";
import "@uniswap-v3-core/interfaces/IUniswapV3Pool.sol";
import "forge-std/Script.sol";

import "@aperture/uni-v3-lib/LiquidityAmounts.sol";
import "@aperture/uni-v3-lib/TickMath.sol";

interface ILM {
    function positions(uint8 stage) external view returns (uint128 liquidity, int24 tickLower, int24 tickUpper);
}

interface IWETH {
    function balanceOf(address) external view returns (uint256);
}

/// @title LmTotalEth
/// @notice Read-only script: prints total ETH controlled by LiquidityManager
///         (free ETH + free WETH + ETH locked in all 3 Uni V3 positions).
///
/// @dev    **What is counted:**
///         1. Free native ETH balance of the LM contract
///         2. Free WETH (ERC-20) balance of the LM contract
///         3. ETH-side principal of all 3 Uniswap V3 positions (FLOOR, ANCHOR, DISCOVERY),
///            computed via LiquidityAmounts.getAmountsForLiquidity at the current sqrtPrice.
///
///         **What is NOT counted:**
///         - Uncollected trading fees accrued inside positions (these only become visible
///           after a recenter() calls pool.burn + pool.collect and rolls them into free WETH).
///         - KRK held by the LM (either as free balance or as the KRK side of positions).
///           KRK fees collected during recenter() are transferred to feeDestination and
///           excluded from this measurement entirely.
///         - KRK sent to feeDestination is also subtracted from outstandingSupply for floor
///           calculation purposes (see LiquidityManager._getOutstandingSupply).
///
///         **Implication for delta_bps:** Because uncollected fees are invisible, delta_bps
///         measured between two LmTotalEth snapshots reflects position principal changes
///         plus any fees that were materialized by a recenter() between snapshots.
///         See evidence/README.md § "Fee-Income Calculation Model" for the full formula.
///
///         forge script script/LmTotalEth.s.sol --rpc-url $RPC_URL
///         Env: LM, WETH, POOL
contract LmTotalEth is Script {
    function run() external view {
        address lm = vm.envAddress("LM");
        address weth = vm.envAddress("WETH");
        address pool = vm.envAddress("POOL");

        // Free balances
        uint256 freeEth = lm.balance;
        uint256 freeWeth = IWETH(weth).balanceOf(lm);

        // Current sqrtPrice from pool
        (uint160 sqrtPriceX96,,,,,,) = IUniswapV3Pool(pool).slot0();

        // Determine which token is WETH (token0 or token1)
        bool wethIsToken0 = IUniswapV3Pool(pool).token0() == weth;

        // Sum ETH in all 3 positions: FLOOR=0, ANCHOR=1, DISCOVERY=2
        uint256 positionEth = 0;
        for (uint8 stage = 0; stage < 3; stage++) {
            (uint128 liquidity, int24 tickLower, int24 tickUpper) = ILM(lm).positions(stage);
            if (liquidity == 0) continue;

            uint160 sqrtA = TickMath.getSqrtRatioAtTick(tickLower);
            uint160 sqrtB = TickMath.getSqrtRatioAtTick(tickUpper);

            (uint256 amount0, uint256 amount1) = LiquidityAmounts.getAmountsForLiquidity(sqrtPriceX96, sqrtA, sqrtB, liquidity);

            positionEth += wethIsToken0 ? amount0 : amount1;
        }

        uint256 total = freeEth + freeWeth + positionEth;

        // Output as plain number for easy bash consumption
        console2.log(total);
    }
}
