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

import "@openzeppelin/contracts/access/AccessControl.sol";
import "./WLPReceiptToken.sol";
import "./interfaces/IWLPProgramEvents.sol";

/**
 * @title PublicChainMintController
 * @notice Destination-chain controller: mints `wLP` once per `lockRef` (replay protection).
 * @dev Relayer must verify Chain 138 `LPLocked` event / attestation off-chain or via future ZK proof.
 */
contract PublicChainMintController is AccessControl, IWLPProgramEvents {
    bytes32 public constant RELAYER_ROLE = keccak256("RELAYER_ROLE");

    WLPReceiptToken public immutable wlp;
    /// @notice Optional Chain 138 locker address for documentation / future cross-verify hooks.
    address public immutable chain138Locker;

    mapping(bytes32 => bool) public mintedForLock;
    bool public mintPaused;

    constructor(address wlp_, address chain138Locker_, address admin) {
        require(wlp_ != address(0) && admin != address(0), "MintCtl: zero");
        wlp = WLPReceiptToken(wlp_);
        chain138Locker = chain138Locker_;
        _grantRole(DEFAULT_ADMIN_ROLE, admin);
    }

    /**
     * @notice Idempotent mint keyed by `lockRef` (must match Chain 138 locker emission).
     */
    function mintForLock(bytes32 lockRef, address recipient, uint256 amount) external onlyRole(RELAYER_ROLE) {
        require(!mintPaused, "MintCtl: paused");
        require(lockRef != bytes32(0), "MintCtl: zero lockRef");
        require(recipient != address(0) && amount > 0, "MintCtl: bad args");
        require(!mintedForLock[lockRef], "MintCtl: replay");
        mintedForLock[lockRef] = true;
        wlp.mint(recipient, amount);
        emit WLPMinted(lockRef, recipient, amount);
    }

    function setMintPaused(bool paused) external onlyRole(DEFAULT_ADMIN_ROLE) {
        mintPaused = paused;
    }
}
