/**
 * Contract deployment example: Deploy a simple contract on ChainID 138
 */

import { ethers } from 'ethers';
import { initTatumSDK } from '../tatum-client';
import { CHAIN_ID, CHAIN_NAME, DEFAULT_RPC_URL } from '../config';

// Simple storage contract bytecode and ABI
const STORAGE_CONTRACT_BYTECODE = '0x608060405234801561001057600080fd5b50610150806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c80632e64cec11461003b5780636057361d14610059575b600080fd5b610043610075565b60405161005091906100d1565b60405180910390f35b610073600480360381019061006e919061009d565b61007e565b005b60008054905090565b8060008190555050565b6000819050919050565b61009a81610087565b81146100a557600080fd5b50565b6000813590506100b781610091565b92915050565b6000602082840312156100d3576100d26000fd5b60006100e1848285016100a8565b91505092915050565b6100f381610087565b82525050565b600060208201905061010e60008301846100ea565b9291505056fea2646970667358221220c5f5c5e5c5e5c5e5c5e5c5e5c5e5c5e5c5e5c5e5c5e5c5e5c5e5c5e5c64736f6c63430008070033';
const STORAGE_CONTRACT_ABI = [
  {
    inputs: [],
    name: 'retrieve',
    outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }],
    stateMutability: 'view',
    type: 'function',
  },
  {
    inputs: [{ internalType: 'uint256', name: 'num', type: 'uint256' }],
    name: 'store',
    outputs: [],
    stateMutability: 'nonpayable',
    type: 'function',
  },
];

async function main() {
  console.log(`Deploying contract on ${CHAIN_NAME} (ChainID ${CHAIN_ID})...`);
  
  // Load private key from environment
  const privateKey = process.env.PRIVATE_KEY;
  if (!privateKey) {
    throw new Error('PRIVATE_KEY environment variable not set');
  }
  
  // Initialize ethers provider with ChainID 138
  const provider = new ethers.JsonRpcProvider(DEFAULT_RPC_URL, {
    chainId: CHAIN_ID,
    name: 'defi-oracle-mainnet',
  });
  
  // Create wallet
  const wallet = new ethers.Wallet(privateKey, provider);
  console.log('Wallet Address:', wallet.address);
  
  // Get balance
  const balance = await provider.getBalance(wallet.address);
  console.log('Balance:', ethers.formatEther(balance), 'ETH');
  
  // Deploy contract
  console.log('\nDeploying Storage contract...');
  const factory = new ethers.ContractFactory(
    STORAGE_CONTRACT_ABI,
    STORAGE_CONTRACT_BYTECODE,
    wallet
  );
  
  const contract = await factory.deploy({
    chainId: CHAIN_ID, // Important: Must match ChainID 138
  });
  
  console.log('Deployment Transaction Hash:', contract.deploymentTransaction()?.hash);
  console.log('Waiting for deployment...');
  
  await contract.waitForDeployment();
  const contractAddress = await contract.getAddress();
  console.log('Contract deployed at:', contractAddress);
  
  // Interact with contract
  console.log('\n=== Interacting with Contract ===');
  
  // Store a value
  const valueToStore = 42;
  console.log(`Storing value: ${valueToStore}`);
  const storeTx = await contract.store(valueToStore, {
    chainId: CHAIN_ID,
  });
  await storeTx.wait();
  console.log('Store transaction confirmed:', storeTx.hash);
  
  // Retrieve the value
  const retrievedValue = await contract.retrieve();
  console.log('Retrieved value:', retrievedValue.toString());
  
  // Verify using Tatum SDK
  console.log('\n=== Verifying Contract with Tatum SDK ===');
  const tatum = await initTatumSDK({
    rpcUrl: DEFAULT_RPC_URL,
    verbose: false,
  });
  
  // Get contract code
  const code = await tatum.rpc.request('eth_getCode', [contractAddress, 'latest']);
  console.log('Contract Code:', code ? 'Present' : 'Not found');
  
  // Get contract storage
  const storageValue = await tatum.rpc.request('eth_getStorageAt', [
    contractAddress,
    '0x0', // Storage slot 0
    'latest',
  ]);
  console.log('Storage Value (slot 0):', storageValue);
  
  console.log('\n=== Contract Deployment Example Complete ===');
  console.log(`Contract Address: ${contractAddress}`);
  console.log(`Explorer: ${process.env.EXPLORER_URL || 'https://explorer.defi-oracle-meta-mainnet.org'}/address/${contractAddress}`);
}

main().catch((error) => {
  console.error('Error:', error);
  process.exit(1);
});

