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

import "forge-std/Script.sol";
import "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol";
import "@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol";

import "../src/Coupon.sol";
import "../src/CouponFactory.sol";
import "../src/Settlement.sol";
import "../src/Redemption.sol";
import "../src/Compliance.sol";
import "../src/Treasury.sol";
import "../src/Governance.sol";
import "../src/ExchangeRateOracle.sol";
import "../src/CouponBackedSecurity.sol";
import "../src/CouponBatch.sol";
import "../src/Redemption1155.sol";

/// @title Deploy — Genex 合约系统完整部署脚本
/// @notice 部署所有合约（Transparent Proxy 模式） + 角色授权 + 初始化
contract Deploy is Script {
    // 部署后的合约地址
    ProxyAdmin public proxyAdmin;
    address public coupon;
    address public couponFactory;
    address public settlement;
    address public redemption;
    address public compliance;
    address public treasury;
    address public governance;
    address public oracle;
    address public cbs;
    address public couponBatch;
    address public redemption1155;

    function run() external {
        uint256 deployerKey = vm.envUint("DEPLOYER_PRIVATE_KEY");
        address deployer = vm.addr(deployerKey);
        address usdc = vm.envAddress("USDC_ADDRESS");
        address platformFeeCollector = vm.envOr("FEE_COLLECTOR", deployer);

        // 多签成员地址
        address[] memory multisigMembers = new address[](5);
        multisigMembers[0] = vm.envOr("MULTISIG_1", deployer);
        multisigMembers[1] = vm.envOr("MULTISIG_2", deployer);
        multisigMembers[2] = vm.envOr("MULTISIG_3", deployer);
        multisigMembers[3] = vm.envOr("MULTISIG_4", deployer);
        multisigMembers[4] = vm.envOr("MULTISIG_5", deployer);

        vm.startBroadcast(deployerKey);

        // ==========================================
        // 1. 部署 ProxyAdmin
        // ==========================================
        proxyAdmin = new ProxyAdmin();
        console.log("ProxyAdmin:", address(proxyAdmin));

        // ==========================================
        // 2. 部署 Compliance（最先，其他合约依赖它）
        // ==========================================
        Compliance complianceImpl = new Compliance();
        compliance = _deployProxy(
            address(complianceImpl),
            abi.encodeCall(Compliance.initialize, (deployer))
        );
        console.log("Compliance:", compliance);

        // ==========================================
        // 3. 部署 Coupon
        // ==========================================
        Coupon couponImpl = new Coupon();
        coupon = _deployProxy(
            address(couponImpl),
            abi.encodeCall(Coupon.initialize, ("Genex Coupon", "GXC", deployer))
        );
        console.log("Coupon:", coupon);

        // ==========================================
        // 4. 部署 CouponFactory
        // ==========================================
        CouponFactory factoryImpl = new CouponFactory();
        couponFactory = _deployProxy(
            address(factoryImpl),
            abi.encodeCall(CouponFactory.initialize, (coupon, compliance, deployer))
        );
        console.log("CouponFactory:", couponFactory);

        // ==========================================
        // 5. 部署 Settlement
        // ==========================================
        Settlement settlementImpl = new Settlement();
        settlement = _deployProxy(
            address(settlementImpl),
            abi.encodeCall(Settlement.initialize, (coupon, compliance, usdc, deployer))
        );
        console.log("Settlement:", settlement);

        // ==========================================
        // 6. 部署 Redemption
        // ==========================================
        Redemption redemptionImpl = new Redemption();
        redemption = _deployProxy(
            address(redemptionImpl),
            abi.encodeCall(Redemption.initialize, (coupon, compliance, deployer))
        );
        console.log("Redemption:", redemption);

        // ==========================================
        // 7. 部署 Treasury
        // ==========================================
        Treasury treasuryImpl = new Treasury();
        treasury = _deployProxy(
            address(treasuryImpl),
            abi.encodeCall(Treasury.initialize, (usdc, platformFeeCollector, deployer))
        );
        console.log("Treasury:", treasury);

        // ==========================================
        // 8. 部署 Governance
        // ==========================================
        Governance governanceImpl = new Governance();
        governance = _deployProxy(
            address(governanceImpl),
            abi.encodeCall(Governance.initialize, (multisigMembers, deployer))
        );
        console.log("Governance:", governance);

        // ==========================================
        // 9. 部署 ExchangeRateOracle
        // ==========================================
        ExchangeRateOracle oracleImpl = new ExchangeRateOracle();
        oracle = _deployProxy(
            address(oracleImpl),
            abi.encodeCall(ExchangeRateOracle.initialize, (900, deployer))
        );
        console.log("ExchangeRateOracle:", oracle);

        // ==========================================
        // 10. 部署 CouponBatch (ERC-1155)
        // ==========================================
        CouponBatch couponBatchImpl = new CouponBatch();
        couponBatch = _deployProxy(
            address(couponBatchImpl),
            abi.encodeCall(CouponBatch.initialize, ("https://genex.io/api/coupon-batch/{id}.json", deployer))
        );
        console.log("CouponBatch:", couponBatch);

        // ==========================================
        // 11. 部署 Redemption1155
        // ==========================================
        Redemption1155 redemption1155Impl = new Redemption1155();
        redemption1155 = _deployProxy(
            address(redemption1155Impl),
            abi.encodeCall(Redemption1155.initialize, (couponBatch, compliance, deployer))
        );
        console.log("Redemption1155:", redemption1155);

        // ==========================================
        // 12. 部署 CouponBackedSecurity
        // ==========================================
        CouponBackedSecurity cbsImpl = new CouponBackedSecurity();
        cbs = _deployProxy(
            address(cbsImpl),
            abi.encodeCall(CouponBackedSecurity.initialize, (coupon, compliance, usdc, deployer))
        );
        console.log("CouponBackedSecurity:", cbs);

        // ==========================================
        // 13. CouponFactory 关联 CouponBatch
        // ==========================================
        CouponFactory(couponFactory).setCouponBatchContract(couponBatch);

        // ==========================================
        // 14. 角色授权
        // ==========================================
        _grantRoles(deployer);

        vm.stopBroadcast();

        // 输出部署摘要
        console.log("\n========== Deployment Summary ==========");
        console.log("ProxyAdmin:          ", address(proxyAdmin));
        console.log("Compliance:          ", compliance);
        console.log("Coupon:              ", coupon);
        console.log("CouponFactory:       ", couponFactory);
        console.log("Settlement:          ", settlement);
        console.log("Redemption:          ", redemption);
        console.log("Treasury:            ", treasury);
        console.log("Governance:          ", governance);
        console.log("ExchangeRateOracle:  ", oracle);
        console.log("CouponBatch:         ", couponBatch);
        console.log("Redemption1155:      ", redemption1155);
        console.log("CouponBackedSecurity:", cbs);
        console.log("=========================================");
    }

    /// @dev 部署 Transparent Proxy
    function _deployProxy(address implementation, bytes memory initData) internal returns (address) {
        TransparentUpgradeableProxy proxy = new TransparentUpgradeableProxy(
            implementation,
            address(proxyAdmin),
            initData
        );
        return address(proxy);
    }

    /// @dev 授予各合约之间的角色
    function _grantRoles(address deployer) internal {
        // CouponFactory 需要 Coupon 的 FACTORY_ROLE
        Coupon(coupon).grantRole(
            keccak256("FACTORY_ROLE"),
            couponFactory
        );

        // Settlement 需要 Coupon 的 SETTLER_ROLE
        Coupon(coupon).grantRole(
            keccak256("SETTLER_ROLE"),
            settlement
        );

        // Redemption 需要通过 Coupon.burn 权限（owner 或 approved）
        // — Redemption 合约中 burn 通过 ownerOf 检查，无需额外角色

        // CouponFactory 需要 CouponBatch 的 FACTORY_ROLE
        CouponBatch(couponBatch).grantRole(
            keccak256("FACTORY_ROLE"),
            couponFactory
        );

        // Redemption1155 需要 CouponBatch 的 BURNER_ROLE
        CouponBatch(couponBatch).grantRole(
            keccak256("BURNER_ROLE"),
            redemption1155
        );

        // Governance 的 MULTISIG_ROLE 在 initialize 中已设置

        console.log("Roles granted successfully");
    }
}
