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

import "./AereRandomnessBeacon.sol";

/**
 * @title AereDrandConsumer
 * @notice Reference example of consuming verifiable randomness on AERE.
 *         Pattern: dApp picks a future drand round, waits for it to be
 *         submitted (by anyone — typically the dApp itself), then reads
 *         the randomness.
 *
 *   This is a minimal lottery — illustration only, not a production lottery.
 *   Any dApp on AERE can use the same pattern. Two lines of integration code.
 */
contract AereDrandConsumer {
    AereRandomnessBeacon public immutable beacon;
    uint64 public targetRound;
    bytes32 public winnerSeed;

    event RandomnessCommitted(uint64 targetRound, uint64 willResolveAt);
    event RandomnessRevealed(uint64 round, bytes32 randomness, bytes32 winnerSeed);

    constructor(AereRandomnessBeacon _beacon) {
        beacon = _beacon;
    }

    /**
     * @notice Commit to a future drand round as the source of randomness.
     *         The round must be in the future at commit time so its
     *         signature cannot already be known.
     */
    function commitToFutureRound(uint64 minSecondsInFuture) external returns (uint64) {
        uint64 targetTime = uint64(block.timestamp) + minSecondsInFuture;
        targetRound = beacon.roundAtTime(targetTime);
        emit RandomnessCommitted(targetRound, beacon.DRAND_GENESIS() + targetRound * beacon.DRAND_PERIOD());
        return targetRound;
    }

    /**
     * @notice Reveal the random outcome. Caller submits the drand signature
     *         for `targetRound` (anyone can; signature is public on api.drand.sh).
     */
    function reveal(bytes calldata signature) external returns (bytes32 randomness) {
        require(targetRound != 0, "Consumer: not committed");
        randomness = beacon.submitRound(targetRound, signature);
        // Derive the winnerSeed deterministically from the randomness + this contract.
        winnerSeed = keccak256(abi.encodePacked(randomness, address(this), targetRound));
        emit RandomnessRevealed(targetRound, randomness, winnerSeed);
    }

    /**
     * @notice If the round has already been submitted by someone else,
     *         just consume it without paying gas for re-submission.
     */
    function consumeExistingRound() external returns (bytes32 randomness) {
        require(targetRound != 0, "Consumer: not committed");
        randomness = beacon.getRandomness(targetRound);
        require(randomness != bytes32(0), "Consumer: round not submitted yet");
        winnerSeed = keccak256(abi.encodePacked(randomness, address(this), targetRound));
        emit RandomnessRevealed(targetRound, randomness, winnerSeed);
    }
}
