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

import {Script, console} from "forge-std/Script.sol";
import "../../../contracts/bridge/trustless/EnhancedSwapRouterV2.sol";
import "../../../contracts/bridge/trustless/RouteTypesV2.sol";

/// @notice Enable UniV3, Balancer, and Curve routes on live EnhancedSwapRouterV2 (Chain 138).
/// Adapters must already be set via initial deploy; this script only enables providers + routes.
contract ConfigureEnhancedSwapRouterV2MultiVenue is Script {
    address constant DEFAULT_ROUTER_V2 = 0xa421706768aEB7fafA2D912C5E10824eF3437ad4;

    address constant CHAIN138_WETH = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2;
    address constant CHAIN138_USDT = 0x004b63A7B5b0E06f6bB6adb4a5F9f590BF3182D1;
    address constant CHAIN138_USDC = 0x71D6687F38b93CCad569Fa6352c876eea967201b;
    address constant CHAIN138_cUSDT = 0x93E66202A11B1772E55407B32B44e5Cd8eda7f22;
    address constant CHAIN138_cUSDC = 0xf22258f57794CC8E06237084b353Ab30fFfa640b;

    address constant CHAIN138_DODO_PROVIDER = 0x3f729632E9553EBacCdE2e9b4c8F2B285b014F2e;
    address constant CHAIN138_POOL_CUSDTCUSDC = 0x9e89bAe009adf128782E19e8341996c596ac40dC;
    address constant CHAIN138_POOL_CUSDTUSDT = 0x866Cb44b59303d8dc5f4F9E3E7A8e8b0bf238d66;
    address constant CHAIN138_POOL_CUSDCUSDC = 0xc39B7D0F40838cbFb54649d327f49a6DAC964062;
    address constant CHAIN138_POOL_WETH_USDT = 0xe227F6C0520c0c6E8786fE56Fa76c4914F861533;
    address constant CHAIN138_POOL_WETH_USDC = 0xb53A0508940b1Ff90F1AAD4f6cb50a7012Fe5593;

    address constant UNISWAP_V3_ROUTER = 0xde9cD8ee2811E6E64a41D5F68Be315d33995975E;
    address constant UNISWAP_QUOTER = 0x6abbB1CEb2468e748a03A00CD6aA9BFE893AFa1f;
    address constant BALANCER_VAULT = 0x96423d7C1727698D8a25EbFB88131e9422d1a3C3;
    bytes32 constant BALANCER_WETH_USDT_POOL_ID =
        0x877cd220759e8c94b82f55450c85d382ae06856c426b56d93092a420facbc324;
    bytes32 constant BALANCER_WETH_USDC_POOL_ID =
        0xd8dfb18a6baf9b29d8c2dbd74639db87ac558af120df5261dab8e2a5de69013b;
    address constant CURVE_3POOL = 0xE440Ec15805BE4C7BabCD17A63B8C8A08a492e0f;

    function run() external {
        require(block.chainid == 138, "ConfigureEnhancedSwapRouterV2MultiVenue: Chain 138 only");

        uint256 deployerPrivateKey = vm.envUint("PRIVATE_KEY");
        address routerAddress = vm.envOr("ENHANCED_SWAP_ROUTER_V2_ADDRESS", DEFAULT_ROUTER_V2);
        EnhancedSwapRouterV2 router = EnhancedSwapRouterV2(payable(routerAddress));

        uint24 wethUsdtFee = uint24(vm.envOr("UNISWAP_V3_WETH_USDT_FEE", uint256(3000)));
        uint24 wethUsdcFee = uint24(vm.envOr("UNISWAP_V3_WETH_USDC_FEE", uint256(500)));

        vm.startBroadcast(deployerPrivateKey);

        _setDodoPair(router, CHAIN138_cUSDT, CHAIN138_cUSDC, CHAIN138_DODO_PROVIDER, CHAIN138_POOL_CUSDTCUSDC);
        _setDodoPair(router, CHAIN138_cUSDT, CHAIN138_USDT, CHAIN138_DODO_PROVIDER, CHAIN138_POOL_CUSDTUSDT);
        _setDodoPair(router, CHAIN138_cUSDC, CHAIN138_USDC, CHAIN138_DODO_PROVIDER, CHAIN138_POOL_CUSDCUSDC);
        _setDodoPair(router, CHAIN138_WETH, CHAIN138_USDT, CHAIN138_DODO_PROVIDER, CHAIN138_POOL_WETH_USDT);
        _setDodoPair(router, CHAIN138_WETH, CHAIN138_USDC, CHAIN138_DODO_PROVIDER, CHAIN138_POOL_WETH_USDC);

        _setUniswapPair(router, CHAIN138_WETH, CHAIN138_USDT, UNISWAP_V3_ROUTER, UNISWAP_QUOTER, wethUsdtFee);
        _setUniswapPair(router, CHAIN138_WETH, CHAIN138_USDC, UNISWAP_V3_ROUTER, UNISWAP_QUOTER, wethUsdcFee);

        _setBalancerPair(router, CHAIN138_WETH, CHAIN138_USDT, BALANCER_VAULT, BALANCER_WETH_USDT_POOL_ID);
        _setBalancerPair(router, CHAIN138_WETH, CHAIN138_USDC, BALANCER_VAULT, BALANCER_WETH_USDC_POOL_ID);

        _setCurvePair(router, CHAIN138_USDT, CHAIN138_USDC, CURVE_3POOL, 0, 1, false);

        router.setProviderEnabled(RouteTypesV2.Provider.Dodo, true);
        router.setProviderEnabled(RouteTypesV2.Provider.UniswapV3, true);
        router.setProviderEnabled(RouteTypesV2.Provider.Balancer, true);
        router.setProviderEnabled(RouteTypesV2.Provider.Curve, true);
        router.setProviderEnabled(RouteTypesV2.Provider.OneInch, false);
        router.setProviderEnabled(RouteTypesV2.Provider.Partner, false);
        router.setProviderEnabled(RouteTypesV2.Provider.DodoV3, false);

        RouteTypesV2.Provider[] memory providers = new RouteTypesV2.Provider[](4);
        providers[0] = RouteTypesV2.Provider.Dodo;
        providers[1] = RouteTypesV2.Provider.UniswapV3;
        providers[2] = RouteTypesV2.Provider.Balancer;
        providers[3] = RouteTypesV2.Provider.Curve;
        router.setRoutingConfig(0, providers);
        router.setRoutingConfig(1, providers);
        router.setRoutingConfig(2, providers);

        vm.stopBroadcast();

        console.log("EnhancedSwapRouterV2 multi-venue configured:", routerAddress);
    }

    function _setDodoPair(EnhancedSwapRouterV2 router, address tokenA, address tokenB, address target, address pool)
        internal
    {
        bytes memory providerData = abi.encode(pool);
        router.setProviderRoute(tokenA, tokenB, RouteTypesV2.Provider.Dodo, target, providerData, true);
        router.setProviderRoute(tokenB, tokenA, RouteTypesV2.Provider.Dodo, target, providerData, true);
    }

    function _setUniswapPair(
        EnhancedSwapRouterV2 router,
        address tokenA,
        address tokenB,
        address target,
        address quoter,
        uint24 fee
    ) internal {
        bytes memory providerData = abi.encode(bytes(""), fee, quoter, false);
        router.setProviderRoute(tokenA, tokenB, RouteTypesV2.Provider.UniswapV3, target, providerData, true);
        router.setProviderRoute(tokenB, tokenA, RouteTypesV2.Provider.UniswapV3, target, providerData, true);
    }

    function _setBalancerPair(
        EnhancedSwapRouterV2 router,
        address tokenA,
        address tokenB,
        address target,
        bytes32 poolId
    ) internal {
        bytes memory providerData = abi.encode(poolId);
        router.setProviderRoute(tokenA, tokenB, RouteTypesV2.Provider.Balancer, target, providerData, true);
        router.setProviderRoute(tokenB, tokenA, RouteTypesV2.Provider.Balancer, target, providerData, true);
    }

    function _setCurvePair(
        EnhancedSwapRouterV2 router,
        address tokenA,
        address tokenB,
        address target,
        int128 i,
        int128 j,
        bool useUnderlying
    ) internal {
        bytes memory providerData = abi.encode(i, j, useUnderlying);
        router.setProviderRoute(tokenA, tokenB, RouteTypesV2.Provider.Curve, target, providerData, true);
        router.setProviderRoute(tokenB, tokenA, RouteTypesV2.Provider.Curve, target, providerData, true);
    }
}
