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

import {Script, console} from "forge-std/Script.sol";
import {CompliantFiatTokenV2} from "../../contracts/tokens/CompliantFiatTokenV2.sol";
import {UniversalAssetRegistry} from "../../contracts/registry/UniversalAssetRegistry.sol";

/**
 * @title DeployAndStageGenericCompliantFiatTokenV2ForChain
 * @notice Deploy a generic GRU c* V2 asset, optionally wire governance / disclosure metadata,
 *         and stage it in UniversalAssetRegistry.
 *
 * Env:
 *   PRIVATE_KEY (required)
 *   TOKEN_NAME (required)
 *   TOKEN_SYMBOL (required)
 *   CURRENCY_CODE (required)
 *   TOKEN_DECIMALS (optional; default 6)
 *   VERSION_TAG (optional; default "2")
 *   INITIAL_OPERATOR (optional; default deployer)
 *   ADMIN / OWNER (optional; default deployer)
 *   INITIAL_SUPPLY (optional; default 0)
 *   FORWARD_CANONICAL (optional; default true)
 *   GOVERNANCE_CONTROLLER (optional)
 *   UNIVERSAL_ASSET_REGISTRY (optional; when set and REGISTER_IN_GRU != 0, registers the asset)
 *   REGISTER_IN_GRU (optional; default 1)
 *   REGISTRY_NAME (optional; default TOKEN_NAME)
 *   REGISTRY_SYMBOL (optional; default TOKEN_SYMBOL.VERSION_TAG lower-suffix style is not enforced)
 *   TOKEN_URI / REGULATORY_DISCLOSURE_URI / REPORTING_URI (optional)
 */
contract DeployAndStageGenericCompliantFiatTokenV2ForChain is Script {
    uint256 internal constant DEFAULT_INITIAL_SUPPLY = 0;

    function run() external {
        uint256 pk = vm.envUint("PRIVATE_KEY");
        address deployer = vm.addr(pk);
        address initialOperator = vm.envOr("INITIAL_OPERATOR", deployer);
        address ownerAlias = vm.envOr("OWNER", deployer);
        address admin = vm.envOr("ADMIN", ownerAlias);
        uint256 initialSupply = vm.envOr("INITIAL_SUPPLY", DEFAULT_INITIAL_SUPPLY);
        bool forwardCanonical = vm.envOr("FORWARD_CANONICAL", true);
        address governanceController = vm.envOr("GOVERNANCE_CONTROLLER", address(0));
        address registryAddr = vm.envOr("UNIVERSAL_ASSET_REGISTRY", address(0));
        bool registerInGru = vm.envOr("REGISTER_IN_GRU", uint256(1)) != 0;

        string memory tokenName = vm.envString("TOKEN_NAME");
        string memory tokenSymbol = vm.envString("TOKEN_SYMBOL");
        string memory currencyCode = vm.envString("CURRENCY_CODE");
        uint8 tokenDecimals = uint8(vm.envOr("TOKEN_DECIMALS", uint256(6)));
        string memory versionTag = vm.envOr("VERSION_TAG", string("2"));
        string memory registryName = vm.envOr("REGISTRY_NAME", tokenName);
        string memory registrySymbol = vm.envOr("REGISTRY_SYMBOL", tokenSymbol);
        string memory tokenURI = vm.envOr("TOKEN_URI", string(""));
        string memory disclosureURI = vm.envOr("REGULATORY_DISCLOSURE_URI", string(""));
        string memory reportingURI = vm.envOr("REPORTING_URI", string(""));

        vm.startBroadcast(pk);

        CompliantFiatTokenV2 token = new CompliantFiatTokenV2(
            tokenName,
            tokenSymbol,
            tokenDecimals,
            currencyCode,
            versionTag,
            initialOperator,
            admin,
            initialSupply,
            forwardCanonical
        );

        if (bytes(tokenURI).length > 0 || bytes(tokenSymbol).length > 0) {
            _setPresentationMetadata(address(token), tokenURI, tokenSymbol);
        }
        if (governanceController != address(0)) {
            _setGovernanceController(address(token), governanceController);
        }
        if (bytes(disclosureURI).length > 0 || bytes(reportingURI).length > 0) {
            _setDisclosureMetadata(address(token), disclosureURI, reportingURI);
        }
        if (registerInGru && registryAddr != address(0)) {
            UniversalAssetRegistry(registryAddr).registerGRUCompliantAsset(
                address(token),
                registryName,
                registrySymbol,
                tokenDecimals,
                "International"
            );
        }

        console.log("generic_cstar_v2", address(token));
        console.log("token_symbol", tokenSymbol);
        console.log("currency_code", currencyCode);

        vm.stopBroadcast();
    }

    function _setPresentationMetadata(address token, string memory tokenURI, string memory symbolDisplay) internal {
        (bool ok,) = token.call(
            abi.encodeWithSignature(
                "emergencySetPresentationMetadata(bool,string,string)",
                true,
                tokenURI,
                symbolDisplay
            )
        );
        require(ok, "emergencySetPresentationMetadata failed");
    }

    function _setGovernanceController(address token, address governanceController) internal {
        (bool ok,) = token.call(
            abi.encodeWithSignature("setGovernanceController(address)", governanceController)
        );
        require(ok, "setGovernanceController failed");
    }

    function _setDisclosureMetadata(address token, string memory disclosureURI, string memory reportingURI) internal {
        (bool ok,) = token.call(
            abi.encodeWithSignature(
                "emergencySetDisclosureMetadata(string,string)",
                disclosureURI,
                reportingURI
            )
        );
        require(ok, "emergencySetDisclosureMetadata failed");
    }
}
