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

import {Script, console2} from "forge-std/Script.sol";
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";

import {Chain138LPLocker} from "../../contracts/wrapped-lp-public/Chain138LPLocker.sol";
import {WLPReceiptToken} from "../../contracts/wrapped-lp-public/WLPReceiptToken.sol";
import {PublicChainMintController} from "../../contracts/wrapped-lp-public/PublicChainMintController.sol";
import {WLPRedemptionGateway} from "../../contracts/wrapped-lp-public/WLPRedemptionGateway.sol";
import {WLPNAVOracle} from "../../contracts/wrapped-lp-public/WLPNAVOracle.sol";
import {WrappedLPNAVVault} from "../../contracts/wrapped-lp-public/WrappedLPNAVVault.sol";

/**
 * @title DeployWrappedLPProgram
 * @notice **Single-chain / local harness:** deploys locker + public stack in one `run()` (only valid when
 *         both sides target the **same** RPC, e.g. Anvil or fork). For production use:
 *         - [DeployWrappedLPLockerChain138.s.sol](DeployWrappedLPLockerChain138.s.sol) with Chain 138 RPC
 *         - [DeployWrappedLPPublicChain.s.sol](DeployWrappedLPPublicChain.s.sol) with destination RPC
 * @dev Env: `LP_TOKEN`, `ADMIN`, `USDC` (optional vault), `PRIVATE_KEY`. Optional `WIRE_ROLES=1` and
 *      `RELAYER_ADDRESS` when `vm.addr(PRIVATE_KEY) == ADMIN`.
 */
contract DeployWrappedLPProgram is Script {
    function run() external {
        address lpToken = vm.envAddress("LP_TOKEN");
        address admin = vm.envAddress("ADMIN");
        uint256 pk = vm.envUint("PRIVATE_KEY");

        vm.startBroadcast(pk);

        Chain138LPLocker locker = new Chain138LPLocker(lpToken, admin);
        console2.log("Chain138LPLocker", address(locker));

        WLPReceiptToken wlp = new WLPReceiptToken("Wrapped LP", "wLP", 18, admin);
        console2.log("WLPReceiptToken", address(wlp));

        PublicChainMintController mintCtl = new PublicChainMintController(address(wlp), address(locker), admin);
        console2.log("PublicChainMintController", address(mintCtl));

        WLPRedemptionGateway gateway = new WLPRedemptionGateway(address(wlp), admin);
        console2.log("WLPRedemptionGateway", address(gateway));

        WLPNAVOracle oracle = new WLPNAVOracle(admin, 3600);
        console2.log("WLPNAVOracle", address(oracle));

        address usdc = vm.envOr("USDC", address(0));
        if (usdc != address(0)) {
            WrappedLPNAVVault vault = new WrappedLPNAVVault(
                IERC20(usdc),
                "Wrapped LP NAV Vault",
                "wLPV",
                admin
            );
            console2.log("WrappedLPNAVVault", address(vault));
        }

        if (vm.envOr("WIRE_ROLES", false)) {
            address deployer = vm.addr(pk);
            require(deployer == admin, "WIRE_ROLES requires deployer==ADMIN");
            address relayerAddr = vm.envAddress("RELAYER_ADDRESS");
            address keeperAddr = vm.envOr("KEEPER_ADDRESS", relayerAddr);
            wlp.grantRole(wlp.MINTER_ROLE(), address(mintCtl));
            wlp.grantRole(wlp.BURNER_ROLE(), address(gateway));
            mintCtl.grantRole(mintCtl.RELAYER_ROLE(), relayerAddr);
            locker.grantRole(locker.BRIDGE_RELEASE_ROLE(), relayerAddr);
            oracle.grantRole(oracle.KEEPER_ROLE(), keeperAddr);
            console2.log("Wired roles (minter/burner/relayer/release/keeper)");
        }

        vm.stopBroadcast();
    }
}
