import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import { Box, Text } from 'ink';
import { useEffect, useState } from 'react';
import { Spinner } from '@inkjs/ui';
import { useConfig } from 'wagmi';
import { useForgeArtifact } from '../../queries/forgeArtifact.js';
import { useMappingChainByIdentifier } from '../../queries/chainByIdentifier.js';
import { privateKeyToAccount } from 'viem/accounts';
import { computeDeploymentParams } from './computeDeploymentParams.js';
import { useMutation } from '@tanstack/react-query';
import { useChecksForChains } from './hooks/useChecksForChains.js';
import { ChooseExecutionOption, } from '../../components/ChooseExecutionOption.js';
import { VerifyCommandInner } from '../../commands/verify.js';
import { deployCreate2 } from './deployCreate2.js';
import { sendAllTransactionTasksWithPrivateKeyAccount, sendAllTransactionTasksWithCustomWalletRpc, } from './sendAllTransactionTasks.js';
import { getSponsoredSenderWalletRpcUrl } from '../../util/sponsoredSender.js';
import { DeployStatus } from './components/DeployStatus.js';
import { createTxSenderFromPrivateKeyAccount } from '../../util/TxSender.js';
// Prepares any required data or loading state if waiting
export const DeployCreate2Command = ({ options, }) => {
    const { data: chainByIdentifier, isLoading: isChainByIdentifierLoading } = useMappingChainByIdentifier();
    const { data: forgeArtifact, isLoading: isForgeArtifactLoading } = useForgeArtifact(options.forgeArtifactPath);
    if (isForgeArtifactLoading ||
        !forgeArtifact ||
        isChainByIdentifierLoading ||
        !chainByIdentifier) {
        return _jsx(Spinner, {});
    }
    // TODO: Fix option formatting between wizard and command
    // Wizards = [ 'op', 'base' ]
    // Command = [ 'op, base' ]
    const flattenedChains = options.chains.flatMap(chain => chain.split(','));
    const chains = flattenedChains.map(x => {
        const chain = chainByIdentifier[`${options.network}/${x}`];
        if (!chain) {
            throw new Error(`Chain ${`${options.network}/${x}`} not found`);
        }
        return chain;
    });
    const intent = {
        chains,
        forgeArtifactPath: options.forgeArtifactPath,
        forgeArtifact,
        constructorArgs: options.constructorArgs?.split(','),
        salt: options.salt,
    };
    const computedParams = computeDeploymentParams(intent);
    return (_jsx(DeployCreate2CommandInner, { deploymentParams: {
            intent,
            computedParams,
        }, options: options }));
};
const DeployCreate2CommandInner = ({ deploymentParams, options, }) => {
    const [executionOption, setExecutionOption] = useState(options.privateKey
        ? { type: 'privateKey', privateKey: options.privateKey }
        : null);
    const { initCode, deterministicAddress, baseSalt } = deploymentParams.computedParams;
    const { chainIdsToDeployTo } = useChecksForChains(deploymentParams);
    const wagmiConfig = useConfig();
    const chainIdsToDeployToSet = new Set(chainIdsToDeployTo);
    const chainsToDeployTo = chainIdsToDeployTo
        ? wagmiConfig.chains.filter(chain => chainIdsToDeployToSet.has(chain.id))
        : undefined;
    const { mutate, data } = useMutation({
        mutationFn: () => {
            if (!chainsToDeployTo) {
                throw new Error('No chains to deploy to');
            }
            const txSender = options.privateKey
                ? createTxSenderFromPrivateKeyAccount(wagmiConfig, privateKeyToAccount(options.privateKey))
                : undefined;
            return deployCreate2({
                wagmiConfig,
                deterministicAddress,
                initCode,
                baseSalt,
                chains: chainsToDeployTo,
                foundryArtifactPath: options.forgeArtifactPath,
                contractArguments: options.constructorArgs?.split(',') ?? [],
                txSender,
            });
        },
    });
    useEffect(() => {
        if (!chainsToDeployTo)
            return;
        mutate();
    }, [chainsToDeployTo?.map(x => x.id).join('-')]);
    return (_jsxs(Box, { flexDirection: "column", gap: 1, children: [_jsxs(Box, { flexDirection: "column", gap: 1, children: [_jsx(Text, { bold: true, underline: true, children: "Deployments" }), _jsxs(Box, { flexDirection: "column", paddingLeft: 2, children: [_jsxs(Text, { children: ["Contract: ", _jsx(Text, { color: "cyan", children: options.forgeArtifactPath })] }), _jsxs(Text, { children: ["Network: ", _jsx(Text, { color: "blue", children: options.network })] }), _jsxs(Text, { children: ["Target Chains:", ' ', _jsx(Text, { color: "green", children: deploymentParams.intent.chains
                                            .map(chain => chain.name)
                                            .join(', ') })] }), _jsxs(Text, { children: ["Salt: ", _jsx(Text, { color: "magenta", children: baseSalt })] }), options.constructorArgs && (_jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { children: "Constructor Arguments:" }), _jsx(Text, { color: "cyan", children: options.constructorArgs.split(',').join(', ') })] })), _jsx(Box, { marginTop: 1, children: _jsxs(Text, { children: ["Address:", ' ', _jsx(Text, { color: "yellow", bold: true, children: deterministicAddress })] }) })] })] }), _jsx(Box, { flexDirection: "column", paddingX: 2, children: _jsxs(Box, { flexDirection: "row", children: [_jsx(Box, { flexDirection: "column", marginRight: 2, children: deploymentParams.intent.chains.map(chain => (_jsxs(Text, { bold: true, color: "blue", children: [chain.name, ":"] }, chain.id))) }), _jsx(Box, { flexDirection: "column", children: deploymentParams.intent.chains.map(chain => (_jsx(DeployStatus, { chain: chain, initCode: initCode, baseSalt: baseSalt, deterministicAddress: deterministicAddress, executionOption: executionOption }, chain.id))) })] }) }), chainsToDeployTo && chainsToDeployTo.length > 0 && !executionOption && (_jsx(Box, { children: _jsx(ChooseExecutionOption, { label: '🚀 Ready to deploy!', onSubmit: async (executionOption) => {
                        if (executionOption.type === 'privateKey') {
                            setExecutionOption(executionOption);
                            await sendAllTransactionTasksWithPrivateKeyAccount(privateKeyToAccount(executionOption.privateKey));
                        }
                        else if (executionOption.type === 'sponsoredSender') {
                            setExecutionOption(executionOption);
                            await sendAllTransactionTasksWithCustomWalletRpc(chainId => getSponsoredSenderWalletRpcUrl(executionOption.apiKey, chainId));
                        }
                        else {
                            setExecutionOption(executionOption);
                        }
                    } }) })), data && (_jsx(CompletedOrVerify, { shouldVerify: !!options.verify, chains: deploymentParams.intent.chains, forgeArtifactPath: options.forgeArtifactPath, contractAddress: deterministicAddress, forgeArtifact: deploymentParams.intent.forgeArtifact }))] }));
};
const CompletedOrVerify = ({ shouldVerify, chains, forgeArtifactPath, contractAddress, forgeArtifact, }) => {
    if (!shouldVerify) {
        // TODO: hacky way to quit until we remove pastel
        setTimeout(() => {
            process.exit(0);
        }, 1);
        return (_jsx(Box, { children: _jsx(Text, { children: "Contract is successfully deployed to all chains" }) }));
    }
    return (_jsx(VerifyCommandInner, { chains: chains, forgeArtifactPath: forgeArtifactPath, contractAddress: contractAddress, forgeArtifact: forgeArtifact }));
};
