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

import "./IRouterClient.sol";

/**
 * @title CCIP Message Validator
 * @notice Validates CCIP messages for replay protection and format
 * @dev Provides message validation utilities
 */
library CCIPMessageValidator {
    // Message nonce tracking per source chain
    struct MessageNonce {
        uint256 nonce;
        bool used;
    }
    
    /**
     * @notice Validate message format
     * @param message The CCIP message to validate
     * @return valid True if message format is valid
     */
    function validateMessageFormat(
        IRouterClient.Any2EVMMessage memory message
    ) internal pure returns (bool valid) {
        // Check message ID is not zero
        if (message.messageId == bytes32(0)) {
            return false;
        }
        
        // Check source chain selector is valid
        if (message.sourceChainSelector == 0) {
            return false;
        }
        
        // Check sender is not empty
        if (message.sender.length == 0) {
            return false;
        }
        
        // Check data is not empty
        if (message.data.length == 0) {
            return false;
        }
        
        return true;
    }
    
    /**
     * @notice Validate oracle data format
     * @param data The encoded oracle data
     * @return valid True if data format is valid
     * @return answer Decoded answer
     * @return roundId Decoded round ID
     * @return timestamp Decoded timestamp
     */
    function validateOracleData(
        bytes memory data
    ) internal view returns (
        bool valid,
        uint256 answer,
        uint256 roundId,
        uint256 timestamp
    ) {
        // Check minimum data length (3 uint256 = 96 bytes)
        if (data.length < 96) {
            return (false, 0, 0, 0);
        }
        
        // Decode oracle data directly (no need for try-catch in library)
        (uint256 _answer, uint256 _roundId, uint256 _timestamp) = abi.decode(data, (uint256, uint256, uint256));
        
        // Validate answer is not zero
        if (_answer == 0) {
            return (false, 0, 0, 0);
        }
        
        // Validate timestamp is reasonable (not too far in future/past)
        // Note: Using uint256 to avoid underflow
        uint256 currentTime = block.timestamp;
        if (_timestamp > currentTime + 300) {
            return (false, 0, 0, 0);
        }
        if (currentTime > _timestamp && currentTime - _timestamp > 3600) {
            return (false, 0, 0, 0);
        }
        
        return (true, _answer, _roundId, _timestamp);
    }
}

