const {ethers} = require("hardhat");
const Safe = require('@safe-global/protocol-kit').default;
const {EthersAdapter} = require('@safe-global/protocol-kit');
const {default: SafeApiKit} = require("@safe-global/api-kit");

const txServiceUrls = {
    ethereum: "https://safe-transaction-mainnet.safe.global",
    base: "https://safe-transaction-base.safe.global",
    unichain: "https://safe-transaction-unichain.safe.global",
};

const txServiceUrl = txServiceUrls[hre.network.name];

async function proposeOrSendTransaction(safeAddress, txData, signer, methodName) {
    if (safeAddress) {
        return proposeTransaction(safeAddress, txData, signer, methodName);
    } else {
        console.log(`Executing the transaction directly`);
        const tx = await signer.sendTransaction(txData);
        await tx.wait();
        return tx.hash;
    }
}

async function proposeTransaction(safeAddress, txData, signer, methodName) {
    const signerAddress = await signer.getAddress();
    console.log(`Proposing transaction to Safe: ${safeAddress} with account: ${signerAddress}`);

    const ethAdapter = new EthersAdapter({
        ethers,
        signerOrProvider: signer,
    });

    const safeService = new SafeApiKit({txServiceUrl, ethAdapter});

    const safeSdk = await Safe.create({
        ethAdapter,
        safeAddress,
    });
    let next_nonce = await safeService.getNextNonce(safeAddress);
    const safeTransaction = await safeSdk.createTransaction({
        safeTransactionData: {
            ...txData,
            nonce: next_nonce
        }
    });
    const safeTxHash = await safeSdk.getTransactionHash(safeTransaction);
    const senderSignature = await safeSdk.signTransactionHash(safeTxHash);

    const proposeArgs = {
        safeAddress,
        safeTransactionData: safeTransaction.data,
        safeTxHash,
        senderAddress: signerAddress,
        senderSignature: senderSignature.data,
        origin: `Proposed from hardhat: ${methodName}`,
        nonce: next_nonce,
    };

    await safeService.proposeTransaction(proposeArgs);
    return safeTxHash;
}

module.exports = {
    proposeOrSendTransaction
}