/**
 * Create Token Bound Account (TBA) Script
 * 
 * This script creates a Token Bound Account (ERC-6551 account) for a specific NFT
 * 
 * Usage:
 * 1. Create a .env file and set the following environment variables:
 *    - PRIVATE_KEY: Private key of the NFT holder 
 * 
 * 2. Run the script:
 *    npm run create-tba
 *    or
 *    yarn create-tba
 */

import { GoTakeSDK, NetworkId } from "../src";
import { getContractAddress } from 'gotake-contracts';
import * as dotenv from 'dotenv';
import { ethers } from 'ethers';

dotenv.config();

async function main() {
    // Check required environment variables
    if (!process.env.PRIVATE_KEY) {
        throw new Error("PRIVATE_KEY is not defined in environment variables. Please set it in your .env file");
    }

    try {
        // Get network ID - using Base Sepolia testnet
        const networkId = NetworkId.BASE_SEPOLIA;
        console.log(`Using network: Base Sepolia (ID: ${networkId})`);

        // Create Provider and Signer
        const rpcUrl = "https://sepolia.base.org";
        const ethersProvider = new ethers.providers.JsonRpcProvider(rpcUrl);
        const ethersSigner = new ethers.Wallet(process.env.PRIVATE_KEY, ethersProvider);
        console.log(`Using address: ${await ethersSigner.getAddress()}`);

        // Initialize SDK
        const sdk = new GoTakeSDK({
            network: networkId,
            provider: ethersProvider,
            signer: ethersSigner,
        });
        console.log("SDK initialized successfully");

        // Get contract addresses and Token ID from config
        const tokenContract = getContractAddress('base_sepolia', 'ipnft');
        const implementation = getContractAddress('base_sepolia', 'accountImplementation');
        const tokenId = 0;

        console.log(`NFT contract address: ${tokenContract}`);
        console.log(`Account implementation address: ${implementation}`);
        console.log(`Token ID: ${tokenId}`);

        // Optional parameters
        const salt = "0x0000000000000000000000000000000000000000000000000000000000000000"; // Optional: Salt for account creation

        // Get current gas price recommendations
        console.log("Getting current gas price recommendations...");
        const gasPrices = await sdk.getGasPrice({
            multiplier: 1.5,          // Increase base fee by 50%
            priorityMultiplier: 1.0   // Same as base priority fee
        });

        console.log("Current gas prices:");
        if (gasPrices.baseFeePerGas) {
            console.log(`Base fee: ${ethers.utils.formatUnits(gasPrices.baseFeePerGas, "gwei")} gwei`);
        }
        console.log(`Max fee per gas: ${ethers.utils.formatUnits(gasPrices.maxFeePerGas, "gwei")} gwei`);
        if (gasPrices.maxPriorityFeePerGas) {
            console.log(`Max priority fee: ${ethers.utils.formatUnits(gasPrices.maxPriorityFeePerGas, "gwei")} gwei`);
        }

        // Business parameters - separate from transaction options
        const businessParams = {
            tokenContract: tokenContract,
            tokenId: tokenId,
            salt: salt, // Optional: Salt for deterministic address generation
        };

        // Transaction options including gas configuration
        const transactionOptions = {
            gasConfig: {
                gasLimit: 500000, // Manual gas limit to prevent estimation issues
                maxFeePerGas: gasPrices.maxFeePerGas, // Use recommended values
                maxPriorityFeePerGas: gasPrices.maxPriorityFeePerGas // Use recommended values
            }
        };
        console.log("Using transaction options with recommended gas values");
        console.log(`Gas Limit: ${transactionOptions.gasConfig.gasLimit}`);

        // Create TBA account with separate business params and options
        console.log("Creating TBA account...");
        const tba = await sdk.account.createTBA(businessParams, transactionOptions);

        console.log("TBA created successfully!");
        console.log(`TBA address: ${tba.tbaAddress}`);
        console.log(`Transaction hash: ${tba.tx.hash}`);

        // Wait for transaction confirmation
        console.log("Waiting for transaction confirmation...");
        await tba.tx.wait();
        console.log("Transaction confirmed");

        // Example of executing a transaction from TBA
        /*
        const executeParams = {
            accountAddress: tba.tbaAddress,
            to: "0x1234567890123456789012345678901234567890", // Example recipient address
            value: ethers.utils.parseEther("0.01"), // Send 0.01 ETH
            data: "0x" // Empty data for a simple ETH transfer
        };
        
        // Use the same transaction options
        console.log("Executing transaction from TBA...");
        const executeResult = await sdk.account.executeTBATransaction(executeParams, transactionOptions);
        console.log(`Execution transaction hash: ${executeResult.tx.hash}`);
        */
    } catch (error) {
        console.error("Error creating TBA:");
        console.error(error);
        process.exitCode = 1;
    }
}

main().catch(error => {
    console.error("Error executing script:");
    console.error(error);
    process.exitCode = 1;
});