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

/**
 * @title IReserveSystem
 * @notice Interface for the GRU Reserve System
 * @dev Defines the core functionality for reserve management, conversion, and redemption
 */
interface IReserveSystem {
    // ============ Events ============

    event ReserveDeposited(
        address indexed asset,
        uint256 amount,
        address indexed depositor,
        bytes32 indexed reserveId
    );

    event ReserveWithdrawn(
        address indexed asset,
        uint256 amount,
        address indexed recipient,
        bytes32 indexed reserveId
    );

    event ConversionExecuted(
        address indexed sourceAsset,
        address indexed targetAsset,
        uint256 sourceAmount,
        uint256 targetAmount,
        bytes32 indexed conversionId,
        uint256 fees
    );

    event RedemptionExecuted(
        address indexed asset,
        uint256 amount,
        address indexed recipient,
        bytes32 indexed redemptionId
    );

    event PriceFeedUpdated(
        address indexed asset,
        uint256 price,
        uint256 timestamp
    );

    // ============ Reserve Management ============

    /**
     * @notice Deposit assets into the reserve system
     * @param asset Address of the asset to deposit
     * @param amount Amount to deposit
     * @return reserveId Unique identifier for this reserve deposit
     */
    function depositReserve(
        address asset,
        uint256 amount
    ) external returns (bytes32 reserveId);

    /**
     * @notice Withdraw assets from the reserve system
     * @param asset Address of the asset to withdraw
     * @param amount Amount to withdraw
     * @param recipient Address to receive the withdrawn assets
     * @return reserveId Unique identifier for this reserve withdrawal
     */
    function withdrawReserve(
        address asset,
        uint256 amount,
        address recipient
    ) external returns (bytes32 reserveId);

    /**
     * @notice Get the total reserve balance for an asset
     * @param asset Address of the asset
     * @return balance Total reserve balance
     */
    function getReserveBalance(address asset) external view returns (uint256 balance);

    /**
     * @notice Get reserve balance for a specific reserve ID
     * @param reserveId Unique identifier for the reserve
     * @return asset Address of the asset
     * @return balance Reserve balance
     */
    function getReserveById(bytes32 reserveId) external view returns (address asset, uint256 balance);

    // ============ Conversion ============

    /**
     * @notice Convert assets using optimal path (XAU triangulation)
     * @param sourceAsset Address of the source asset
     * @param targetAsset Address of the target asset
     * @param amount Amount to convert
     * @return conversionId Unique identifier for this conversion
     * @return targetAmount Amount received after conversion
     * @return fees Total fees charged
     */
    function convertAssets(
        address sourceAsset,
        address targetAsset,
        uint256 amount
    ) external returns (
        bytes32 conversionId,
        uint256 targetAmount,
        uint256 fees
    );

    /**
     * @notice Calculate conversion amount without executing
     * @param sourceAsset Address of the source asset
     * @param targetAsset Address of the target asset
     * @param amount Amount to convert
     * @return targetAmount Expected amount after conversion
     * @return fees Expected fees
     * @return path Optimal conversion path
     */
    function calculateConversion(
        address sourceAsset,
        address targetAsset,
        uint256 amount
    ) external view returns (
        uint256 targetAmount,
        uint256 fees,
        address[] memory path
    );

    // ============ Redemption ============

    /**
     * @notice Redeem assets from the reserve system
     * @param asset Address of the asset to redeem
     * @param amount Amount to redeem
     * @param recipient Address to receive the redeemed assets
     * @return redemptionId Unique identifier for this redemption
     */
    function redeem(
        address asset,
        uint256 amount,
        address recipient
    ) external returns (bytes32 redemptionId);

    // ============ Price Feeds ============

    /**
     * @notice Update price feed for an asset
     * @param asset Address of the asset
     * @param price Current price
     * @param timestamp Price timestamp
     */
    function updatePriceFeed(
        address asset,
        uint256 price,
        uint256 timestamp
    ) external;

    /**
     * @notice Get current price for an asset
     * @param asset Address of the asset
     * @return price Current price
     * @return timestamp Price timestamp
     */
    function getPrice(address asset) external view returns (uint256 price, uint256 timestamp);

    /**
     * @notice Get price for conversion between two assets
     * @param sourceAsset Address of the source asset
     * @param targetAsset Address of the target asset
     * @return price Conversion price (target per source)
     */
    function getConversionPrice(
        address sourceAsset,
        address targetAsset
    ) external view returns (uint256 price);
}

