import { config } from 'dotenv';
import { Connection, Keypair, PublicKey } from '@solana/web3.js';
import { AnchorProvider, Wallet } from '@coral-xyz/anchor';
import { getAssociatedTokenAddress, transfer, getAccount } from '@solana/spl-token';
import bs58 from 'bs58';
import fs from 'fs';

// Load environment variables
config();

async function fundDistributorV6() {
  console.log('💰 Funding Merkle Distributor V6 with 1 USDC\n');

  // Load distributor info
  let distributorInfo: any;
  try {
    const infoFile = fs.readFileSync('./distributor-v6-fixed-v2-info.json', 'utf-8');
    distributorInfo = JSON.parse(infoFile);
  } catch (error) {
    throw new Error('Could not load distributor-v6-fixed-v2-info.json. Make sure you have created the V6 distributor first.');
  }

  // Validate environment variables
  const privateKey = process.env.PRIVATE_KEY;
  const rpcEndpoint = process.env.RPC_ENDPOINT || 'https://mainnet.helius-rpc.com/?api-key=616ef0ca-f8ff-499b-8ca2-cd967fb07ef2';
  const walletAddress = process.env.WALLET_ADDRESS || "CoJebSiqLWbXmSCmSSis8NSjva4ag93isJV7dxcz8x5q";

  if (!privateKey) {
    throw new Error('PRIVATE_KEY not found in environment variables');
  }

  console.log('📋 Configuration:');
  console.log(`RPC Endpoint: ${rpcEndpoint}`);
  console.log(`Wallet Address: ${walletAddress}`);
  console.log(`Distributor PDA: ${distributorInfo.distributorPDA}`);
  console.log(`Mint: ${distributorInfo.mint}`);
  console.log(`Version: ${distributorInfo.version} (V6 - FIXED V2)`);

  // Setup connection and wallet
  const connection = new Connection(rpcEndpoint, 'confirmed');
  const keypair = Keypair.fromSecretKey(bs58.decode(privateKey));
  const wallet = new Wallet(keypair);

  console.log(`\n🔑 Connected wallet: ${wallet.publicKey.toString()}`);
  
  if (wallet.publicKey.toString() !== walletAddress) {
    throw new Error('Wallet address mismatch! Check your PRIVATE_KEY and WALLET_ADDRESS');
  }

  const distributorPDA = new PublicKey(distributorInfo.distributorPDA);
  const mint = new PublicKey(distributorInfo.mint);

  // Get token accounts
  const sourceTokenAccount = await getAssociatedTokenAddress(mint, wallet.publicKey);
  const distributorTokenVault = await getAssociatedTokenAddress(
    mint,
    distributorPDA,
    true // allowOwnerOffCurve
  );

  console.log('\n💰 Token Account Details:');
  console.log(`  Source (Your Wallet): ${sourceTokenAccount.toString()}`);
  console.log(`  Destination (Distributor Vault): ${distributorTokenVault.toString()}`);

  // Check current balances
  try {
    const sourceAccount = await getAccount(connection, sourceTokenAccount);
    console.log(`  Current Source Balance: ${sourceAccount.amount.toString()} (${Number(sourceAccount.amount) / 1000000} USDC)`);
  } catch (error) {
    throw new Error('Source token account does not exist or has no USDC. You need USDC in your wallet to fund the distributor.');
  }

  try {
    const vaultAccount = await getAccount(connection, distributorTokenVault);
    console.log(`  Current Vault Balance: ${vaultAccount.amount.toString()} (${Number(vaultAccount.amount) / 1000000} USDC)`);
  } catch (error) {
    console.log('  Current Vault Balance: 0 USDC (account not initialized yet)');
  }

  const amountToTransfer = 1000000; // 1 USDC (6 decimals)
  console.log(`\n📤 Transferring ${amountToTransfer / 1000000} USDC to distributor vault...`);

  try {
    const signature = await transfer(
      connection,
      wallet.payer,
      sourceTokenAccount,
      distributorTokenVault,
      wallet.publicKey,
      amountToTransfer
    );

    console.log(`✅ Transfer successful!`);
    console.log(`Transaction signature: ${signature}`);
    console.log(`View on Solana Explorer: https://explorer.solana.com/tx/${signature}?cluster=mainnet-beta`);

    // Verify the transfer
    console.log('\n🔍 Verifying transfer...');
    
    try {
      const updatedVaultAccount = await getAccount(connection, distributorTokenVault);
      console.log(`✅ Updated Vault Balance: ${updatedVaultAccount.amount.toString()} (${Number(updatedVaultAccount.amount) / 1000000} USDC)`);
    } catch (error) {
      console.log('❌ Could not verify vault balance after transfer');
    }

    try {
      const updatedSourceAccount = await getAccount(connection, sourceTokenAccount);
      console.log(`Updated Source Balance: ${updatedSourceAccount.amount.toString()} (${Number(updatedSourceAccount.amount) / 1000000} USDC)`);
    } catch (error) {
      console.log('Could not check updated source balance');
    }

    console.log('\n🎉 SUCCESS! Distributor V6 is now funded and ready for claims!');
    console.log('📝 Next steps:');
    console.log('   1. Run the V6 claim script to test the complete flow');
    console.log('   2. Verify that the claim works without any errors');
    console.log('   3. Celebrate the complete resolution of InvalidProof errors!');
    console.log('\n🚀 Ready to run: npx ts-node scripts/claim-tokens-v6-fixed.ts');

  } catch (error) {
    console.error('\n❌ Error funding distributor:', error);
    
    if (error instanceof Error) {
      if (error.message.includes('insufficient funds')) {
        console.log('\n💡 You need more USDC in your wallet to fund the distributor.');
        console.log('   Make sure you have at least 1 USDC in your token account.');
      } else if (error.message.includes('TokenAccountNotFoundError')) {
        console.log('\n💡 Token account issue. This might be normal for a new distributor vault.');
      }
    }
    
    throw error;
  }
}

// Run the script
if (require.main === module) {
  fundDistributorV6()
    .then(() => process.exit(0))
    .catch((error) => {
      console.error('Script failed:', error);
      process.exit(1);
    });
}

export { fundDistributorV6 }; 