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

import { MerkleDistributor } from '../src/index';

// Load environment variables
config();

export interface QueryDistributionsParams {
  rpcEndpoint?: string;
  mint: string;
  maxVersion?: number;
  checkVersions?: number[]; // Specific versions to check
  showDetails?: boolean; // Show detailed info for each distributor
}

async function queryDistributions(params: QueryDistributionsParams) {
  console.log('🔍 Querying Distributions\n');

  const {
    rpcEndpoint = 'https://api.mainnet-beta.solana.com',
    maxVersion = 100,
    checkVersions = [],
    showDetails = false
  } = params;

  console.log('📋 Query Configuration:');
  console.log(`RPC Endpoint: ${rpcEndpoint}`);
  console.log(`Token Mint: ${params.mint}`);
  console.log(`Max Version Check: ${maxVersion}`);
  console.log(`Show Details: ${showDetails}\n`);

  // Setup connection (no wallet needed for queries)
  const connection = new Connection(rpcEndpoint, 'confirmed');
  
  // Create a dummy wallet for SDK initialization (not needed for queries)
  const dummyKeypair = Keypair.generate();
  const dummyWallet = new Wallet(dummyKeypair);
  const provider = new AnchorProvider(connection, dummyWallet, { commitment: 'confirmed' });

  // Initialize SDK
  const sdk = new MerkleDistributor(provider);
  const mint = new PublicKey(params.mint);

  try {
    // Get comprehensive overview
    console.log('📊 Getting Distribution Overview...');
    const overview = await sdk.getDistributionOverview(mint, maxVersion);
    
    console.log('\n🎯 Distribution Overview:');
    console.log(`  Mint: ${overview.mint.toString()}`);
    console.log(`  Total Distributors: ${overview.totalDistributors}`);
    console.log(`  Used Versions: [${overview.usedVersions.join(', ')}]`);
    console.log(`  Next Available Version: ${overview.nextAvailableVersion}`);
    console.log(`  Total Claimed: ${overview.totalClaimed} base units`);
    console.log(`  Total Unclaimed: ${overview.totalUnclaimed} base units`);

    if (overview.totalDistributors === 0) {
      console.log('\n✨ No distributors found for this mint!');
      console.log(`💡 You can create the first distributor using version 0`);
      return;
    }

    // Show individual distributors
    console.log('\n📋 Individual Distributors:');
    for (const [version, info] of overview.distributors) {
      console.log(`\n  📦 Version ${version}:`);
      console.log(`    PDA: ${info.pda.toString()}`);
      console.log(`    Admin: ${info.account.admin.toString()}`);
      console.log(`    Max Claim: ${info.account.maxTotalClaim.toString()} base units`);
      console.log(`    Claimed: ${info.claimedAmount} base units`);
      console.log(`    Remaining: ${info.remainingAmount} base units`);
      console.log(`    Clawback Receiver: ${info.account.clawbackReceiver.toString()}`);
      
      if (showDetails) {
        console.log(`    Start Vesting: ${new Date(Number(info.account.startTs.toString()) * 1000).toLocaleString()}`);
        console.log(`    End Vesting: ${new Date(Number(info.account.endTs.toString()) * 1000).toLocaleString()}`);
        console.log(`    Clawback Start: ${new Date(Number(info.account.clawbackStartTs.toString()) * 1000).toLocaleString()}`);
        console.log(`    Max Nodes: ${info.account.maxNumNodes.toString()}`);
        console.log(`    Merkle Root: ${Buffer.from(info.account.root).toString('hex')}`);
      }
    }

    // Check specific versions if requested
    if (checkVersions.length > 0) {
      console.log('\n🔍 Checking Specific Versions:');
      const versionResults = await sdk.batchCheckVersions(mint, checkVersions.map(v => BigInt(v)));
      
      for (const [version, available] of versionResults) {
        const status = available ? '✅ Available' : '❌ Taken';
        console.log(`  Version ${version}: ${status}`);
      }
    }

    // Show next few available versions
    console.log('\n🔮 Next Available Versions:');
    let nextVersion = overview.nextAvailableVersion;
    for (let i = 0; i < 5; i++) {
      console.log(`  ${nextVersion + BigInt(i)}: Available`);
    }

    console.log('\n💡 Usage Tips:');
    console.log('  • Use the next available version for new distributions');
    console.log('  • Check remaining amounts to see if funds are available');
    console.log('  • Monitor claimed amounts to track distribution progress');

  } catch (error) {
    console.error('\n❌ Error querying distributions:', error);
    
    if (error instanceof Error) {
      if (error.message.includes('could not find account')) {
        console.log('💡 This might mean no distributors exist for this mint yet');
      } else if (error.message.includes('Invalid public key')) {
        console.log('💡 Check that the mint address is valid');
      }
    }
    
    throw error;
  }
}

// CLI interface when run directly
if (require.main === module) {
  const args = process.argv.slice(2);
  
  if (args.includes('--help') || args.includes('-h')) {
    console.log(`
Usage: npx ts-node query-distributions.ts [options]

Options:
  --mint <address>          Token mint address (required)
  --max-version <number>    Maximum version to check (default: 100)
  --check-version <number>  Check specific version (can be used multiple times)
  --details                 Show detailed information for each distributor
  --rpc <endpoint>          Custom RPC endpoint

Examples:
  # Query all USDC distributors
  npx ts-node query-distributions.ts \\
    --mint EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v

  # Check specific versions with details
  npx ts-node query-distributions.ts \\
    --mint EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v \\
    --check-version 0 --check-version 5 --check-version 10 \\
    --details

  # Quick check with limited scope
  npx ts-node query-distributions.ts \\
    --mint EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v \\
    --max-version 20
    `);
    process.exit(0);
  }

  // Parse CLI arguments
  const parseCliArgs = (): QueryDistributionsParams => {
    const params: QueryDistributionsParams = {
      mint: '',
      checkVersions: []
    };

    for (let i = 0; i < args.length; i++) {
      const arg = args[i];
      const next = args[i + 1];

      switch (arg) {
        case '--mint':
          params.mint = next;
          i++;
          break;
        case '--max-version':
          params.maxVersion = parseInt(next);
          i++;
          break;
        case '--check-version':
          params.checkVersions!.push(parseInt(next));
          i++;
          break;
        case '--details':
          params.showDetails = true;
          break;
        case '--rpc':
          params.rpcEndpoint = next;
          i++;
          break;
      }
    }

    return params;
  };

  const params = parseCliArgs();

  if (!params.mint) {
    console.error('Error: --mint is required');
    console.error('Use --help for usage information');
    process.exit(1);
  }

  queryDistributions(params)
    .then(() => {
      console.log('\n✅ Query completed successfully');
      process.exit(0);
    })
    .catch((error) => {
      console.error('Query failed:', error);
      process.exit(1);
    });
}

export { queryDistributions }; 