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

import { MockToken } from "./MockToken.sol";

/**
 * @title BacktestKraiken
 * @notice Kraiken-compatible ERC-20 for backtesting purposes only.
 *
 * Dual mint interface:
 *   - MockToken.mint(address to, uint256 amount) — public, inherited from MockToken.
 *     Used by EventReplayer to seed historical pool positions without access checks.
 *   - mint(uint256 amount)                       — restricted to liquidityManager.
 *     Mirrors Kraiken.mint(uint256) so LiquidityManager operates unchanged.
 *
 * burn(uint256), setPreviousTotalSupply(), outstandingSupply(), and peripheryContracts()
 * mirror the real Kraiken interface that LiquidityManager depends on.
 *
 * Omissions vs real Kraiken (acceptable for backtesting):
 *   - No staking pool proportional minting (no Stake.sol deployed).
 *   - No ERC20Permit extension.
 *   - setLiquidityManager() has no deployer-only guard (script context only).
 */
contract BacktestKraiken is MockToken {
    address public liquidityManager;
    uint256 public previousTotalSupply;

    constructor() MockToken("Backtesting KRK", "bKRK", 18) { }

    modifier onlyLiquidityManager() {
        require(msg.sender == liquidityManager, "only liquidity manager");
        _;
    }

    // -------------------------------------------------------------------------
    // Wiring
    // -------------------------------------------------------------------------

    /**
     * @notice Wire the LiquidityManager. Can only be called once.
     */
    function setLiquidityManager(address lm) external {
        require(liquidityManager == address(0), "already set");
        liquidityManager = lm;
    }

    // -------------------------------------------------------------------------
    // LM-restricted supply management (mirrors Kraiken interface)
    // -------------------------------------------------------------------------

    /**
     * @notice Mint `amount` tokens to the LiquidityManager.
     *         Overloads MockToken.mint(address,uint256) — the two signatures
     *         have distinct ABI selectors and coexist without conflict.
     */
    function mint(uint256 amount) external onlyLiquidityManager {
        if (amount > 0) _mint(liquidityManager, amount);
        if (previousTotalSupply == 0) previousTotalSupply = totalSupply();
    }

    /**
     * @notice Burn `amount` tokens from the LiquidityManager's balance.
     */
    function burn(uint256 amount) external onlyLiquidityManager {
        if (amount > 0) _burn(liquidityManager, amount);
    }

    /**
     * @notice Called by LM when isUp == true during recenter.
     */
    function setPreviousTotalSupply(uint256 ts) external onlyLiquidityManager {
        previousTotalSupply = ts;
    }

    // -------------------------------------------------------------------------
    // View helpers (mirrors Kraiken interface)
    // -------------------------------------------------------------------------

    /**
     * @notice Total supply minus the LM's own balance (trader-held supply).
     */
    function outstandingSupply() external view returns (uint256) {
        return totalSupply() - balanceOf(liquidityManager);
    }

    /**
     * @notice Returns (liquidityManager, address(0)) — no staking pool in backtests.
     *         LiquidityManager._getOutstandingSupply() calls this to exclude staked KRK;
     *         returning address(0) for stakingPool skips that subtraction safely.
     */
    function peripheryContracts() external view returns (address, address) {
        return (liquidityManager, address(0));
    }
}
