// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

/**
 * @title ILending
 * @notice 借贷池核心接口
 */
interface ILending {
    
    // ========== Events ==========
    event Supply(address indexed from, address indexed dst, uint256 amount);
    event Withdraw(address indexed src, address indexed to, uint256 amount);
    event SupplyCollateral(address indexed from, address indexed dst, address indexed asset, uint256 amount);
    event WithdrawCollateral(address indexed src, address indexed to, address indexed asset, uint256 amount);
    
    /// @notice 清算债务事件
    event AbsorbDebt(address indexed absorber, address indexed borrower, uint256 basePaidOut, uint256 usdValue);
    
    /// @notice 清算抵押品事件
    event AbsorbCollateral(address indexed absorber, address indexed borrower, address indexed asset, uint256 collateralAbsorbed, uint256 usdValue);
    
    event BuyCollateral(address indexed buyer, address indexed asset, uint256 baseAmount, uint256 collateralAmount);
    
    /// @notice 储备金提取事件
    event WithdrawReserves(address indexed to, uint256 amount);
    
    // ========== Errors ==========
    error Unauthorized();
    error InsufficientBalance();
    error InsufficientCollateral();
    error BorrowTooSmall();
    error NotLiquidatable();
    error SupplyCapExceeded();
    error InvalidLiquidationFactor();
    error InvalidBorrowCollateralFactor();
    error InvalidLiquidateCollateralFactor();
    error InsufficientReserves();
    error NotForSale();
    
    // ========== Core Functions ==========
    
    /**
     * @notice 存入基础资产
     * @param amount 存入金额
     */
    function supply(uint256 amount) external;
    
    /**
     * @notice 取出基础资产
     * @param amount 取出金额
     */
    function withdraw(uint256 amount) external;
    
    /**
     * @notice 存入抵押品
     * @param asset 抵押品地址
     * @param amount 抵押品数量
     */
    function supplyCollateral(address asset, uint256 amount) external;
    
    /**
     * @notice 取出抵押品
     * @param asset 抵押品地址
     * @param amount 抵押品数量
     */
    function withdrawCollateral(address asset, uint256 amount) external;
    
    /**
     * @notice 借款（通过取出超过存款的基础资产实现）
     * @param amount 借款金额
     */
    function borrow(uint256 amount) external;
    
    /**
     * @notice 清算不良债务（单个）
     * @param borrower 待清算的借款人地址
     */
    function absorb(address borrower) external;
    
    /**
     * @notice 批量清算不良债务
     * @param absorber 清算发起人地址
     * @param accounts 待清算的借款人地址数组
     */
    function absorbMultiple(address absorber, address[] calldata accounts) external;
    
    /**
     * @notice 购买清算后的抵押品
     * @param asset 抵押品地址
     * @param minAmount 最小购买量
     * @param baseAmount 支付的基础资产数量
     * @param recipient 接收抵押品的地址
     */
    function buyCollateral(address asset, uint256 minAmount, uint256 baseAmount, address recipient) external;
    
    // ========== View Functions ==========
    
    /**
     * @notice 获取用户基础资产余额
     * @param account 用户地址
     * @return 余额（正数=存款，负数=借款）
     */
    function getBalance(address account) external view returns (int256);
    
    /**
     * @notice 获取用户抵押品余额
     * @param account 用户地址
     * @param asset 抵押品地址
     * @return 抵押品数量
     */
    function getCollateral(address account, address asset) external view returns (uint256);
    
    /**
     * @notice 检查账户是否可被清算
     * @param account 用户地址
     * @return 是否可清算
     */
    function isLiquidatable(address account) external view returns (bool);
    
    /**
     * @notice 获取当前供应利率
     * @return 供应利率 (年化，scaled by 1e18)
     */
    function getSupplyRate() external view returns (uint64);
    
    /**
     * @notice 获取当前借款利率
     * @return 借款利率 (年化，scaled by 1e18)
     */
    function getBorrowRate() external view returns (uint64);
    
    /**
     * @notice 获取用户存款余额（只返回正数部分，ERC20兼容）
     * @param account 用户地址
     * @return 存款余额
     */
    function balanceOf(address account) external view returns (uint256);
    
    /**
     * @notice 获取用户借款余额（只返回债务部分）
     * @param account 用户地址
     * @return 借款余额
     */
    function borrowBalanceOf(address account) external view returns (uint256);
    
    /**
     * @notice 计算支付指定baseAmount可购买的抵押品数量
     * @param asset 抵押品地址
     * @param baseAmount 支付的基础资产数量
     * @return 可购买的抵押品数量
     */
    function quoteCollateral(address asset, uint256 baseAmount) external view returns (uint256);
    
    /**
     * @notice 获取协议储备金
     * @return 储备金余额（可能为负）
     */
    function getReserves() external view returns (int256);
    
    /**
     * @notice 获取抵押品库存
     * @param asset 抵押品地址
     * @return 库存数量
     */
    function getCollateralReserves(address asset) external view returns (uint256);
    
    /**
     * @notice 获取市场利用率
     * @return 利用率（scaled by 1e18）
     */
    function getUtilization() external view returns (uint256);
    
    /**
     * @notice 提取协议储备金（仅 owner）
     * @param to 接收地址
     * @param amount 提取数量
     */
    function withdrawReserves(address to, uint256 amount) external;
}

