/**
 * Holdout scenario: passive-confidence / no-dilution
 *
 * Verifies that a passive holder's balance is not diluted when a new buyer enters.
 * Two wallets buy KRK sequentially. The first buyer's balance must remain exactly
 * the same after the second buyer purchases. The second buyer should receive fewer
 * tokens per ETH due to price impact from the AMM curve.
 *
 * Uses Anvil accounts 4 and 5 (distinct from e2e tests which use account 0).
 */
import { expect, test } from '@playwright/test';
import { Wallet } from 'ethers';
import { createWalletContext } from '../../../../tests/setup/wallet-provider';
import { getStackConfig } from '../../../../tests/setup/stack';
import { connectWallet, getKrkBalance } from '../../helpers/wallet';
import { buyKrk } from '../../helpers/swap';

// Anvil account 4
const PK_A = '0x47e179ec197488593b187f80a00eb0da91f1b9d0b13f8733639f19c30a34926a';
const ADDRESS_A = new Wallet(PK_A).address; // 0x15d34AAf54267DB7D7c367839AAf71A00a2C6A65

// Anvil account 5
const PK_B = '0x8b3a350cf5c34c9194ca85829a2df0ec3153be0318b5e2d3348e872092edffba';
const ADDRESS_B = new Wallet(PK_B).address; // 0x9965507D1a55bcC2695C58ba16FB37d819B0A4dc

test('passive holders are not diluted', async ({ browser }) => {
  const config = getStackConfig();

  // ── 0. Verify both accounts start with 0 KRK ──────────────────────────
  const krkInitialA = await getKrkBalance(config.rpcUrl, config.contracts.Kraiken, ADDRESS_A);
  const krkInitialB = await getKrkBalance(config.rpcUrl, config.contracts.Kraiken, ADDRESS_B);
  
  console.log(`[TEST] Wallet A initial KRK: ${krkInitialA}`);
  console.log(`[TEST] Wallet B initial KRK: ${krkInitialB}`);
  
  expect(krkInitialA).toBe(0n);
  expect(krkInitialB).toBe(0n);
  console.log('[TEST] ✅ Both wallets start with 0 KRK');

  // ── 1. Wallet A buys 1 ETH worth of KRK ────────────────────────────────
  console.log('[TEST] Creating wallet context for Wallet A...');
  const ctxA = await createWalletContext(browser, {
    privateKey: PK_A,
    rpcUrl: config.rpcUrl,
  });
  const pageA = await ctxA.newPage();

  pageA.on('console', msg => console.log(`[BROWSER A] ${msg.type()}: ${msg.text()}`));
  pageA.on('pageerror', err => console.log(`[BROWSER ERROR A] ${err.message}`));

  try {
    console.log('[TEST] Loading web app for Wallet A...');
    await pageA.goto(`${config.webAppUrl}/app/`, { waitUntil: 'domcontentloaded' });
    await expect(pageA.locator('.navbar-title').first()).toBeVisible({ timeout: 30_000 });

    console.log('[TEST] Connecting Wallet A...');
    await connectWallet(pageA);

    console.log('[TEST] Wallet A buying 1 ETH of KRK...');
    await buyKrk(pageA, '1', undefined, 'walletA');

    const krkBalanceA = await getKrkBalance(config.rpcUrl, config.contracts.Kraiken, ADDRESS_A);
    console.log(`[TEST] Wallet A KRK balance after buy: ${krkBalanceA}`);
    expect(krkBalanceA).toBeGreaterThan(0n);
    console.log('[TEST] ✅ Wallet A received KRK');

    // ── 2. Record A's balance and close context ───────────────────────────
    const krkAfterFirstBuy = krkBalanceA;
    console.log(`[TEST] Recorded Wallet A balance: ${krkAfterFirstBuy}`);
  } finally {
    await ctxA.close();
    console.log('[TEST] Closed Wallet A context');
  }

  // Re-query A's balance after closing context to ensure we have the final value
  const krkAfterFirstBuy = await getKrkBalance(config.rpcUrl, config.contracts.Kraiken, ADDRESS_A);
  console.log(`[TEST] Wallet A final balance after first buy: ${krkAfterFirstBuy}`);

  // ── 3. Wallet B buys 5 ETH worth of KRK ────────────────────────────────
  console.log('[TEST] Creating wallet context for Wallet B...');
  const ctxB = await createWalletContext(browser, {
    privateKey: PK_B,
    rpcUrl: config.rpcUrl,
  });
  const pageB = await ctxB.newPage();

  pageB.on('console', msg => console.log(`[BROWSER B] ${msg.type()}: ${msg.text()}`));
  pageB.on('pageerror', err => console.log(`[BROWSER ERROR B] ${err.message}`));

  try {
    console.log('[TEST] Loading web app for Wallet B...');
    await pageB.goto(`${config.webAppUrl}/app/`, { waitUntil: 'domcontentloaded' });
    await expect(pageB.locator('.navbar-title').first()).toBeVisible({ timeout: 30_000 });

    console.log('[TEST] Connecting Wallet B...');
    await connectWallet(pageB);

    console.log('[TEST] Wallet B buying 5 ETH of KRK...');
    await buyKrk(pageB, '5', undefined, 'walletB');

    const krkBalanceB = await getKrkBalance(config.rpcUrl, config.contracts.Kraiken, ADDRESS_B);
    console.log(`[TEST] Wallet B KRK balance after buy: ${krkBalanceB}`);
    expect(krkBalanceB).toBeGreaterThan(0n);
    console.log('[TEST] ✅ Wallet B received KRK');
  } finally {
    await ctxB.close();
    console.log('[TEST] Closed Wallet B context');
  }

  // ── 4. Verify A's balance unchanged (no dilution) ──────────────────────
  const krkBalanceAFinal = await getKrkBalance(config.rpcUrl, config.contracts.Kraiken, ADDRESS_A);
  console.log(`[TEST] Wallet A balance after Wallet B buy: ${krkBalanceAFinal}`);
  console.log(`[TEST] Expected: ${krkAfterFirstBuy}`);
  
  expect(krkBalanceAFinal).toBe(krkAfterFirstBuy);
  console.log('[TEST] ✅ Wallet A balance unchanged — no dilution');

  // ── 5. Verify B got fewer tokens per ETH due to price impact ───────────
  const krkBalanceBFinal = await getKrkBalance(config.rpcUrl, config.contracts.Kraiken, ADDRESS_B);
  
  const tokensPerEthA = krkAfterFirstBuy / 1n; // Bought with 1 ETH
  const tokensPerEthB = krkBalanceBFinal / 5n; // Bought with 5 ETH
  
  console.log(`[TEST] Wallet A tokens per ETH: ${tokensPerEthA}`);
  console.log(`[TEST] Wallet B tokens per ETH: ${tokensPerEthB}`);
  
  expect(tokensPerEthB).toBeLessThan(tokensPerEthA);
  console.log('[TEST] ✅ Wallet B got fewer tokens per ETH (price impact verified)');

  // ── Summary ─────────────────────────────────────────────────────────────
  console.log('');
  console.log('═══════════════════════════════════════════════════════════');
  console.log('  PASSIVE CONFIDENCE: NO DILUTION TEST RESULTS');
  console.log('═══════════════════════════════════════════════════════════');
  console.log(`  Wallet A (1 ETH):   ${krkAfterFirstBuy} KRK (${tokensPerEthA} per ETH)`);
  console.log(`  Wallet B (5 ETH):   ${krkBalanceBFinal} KRK (${tokensPerEthB} per ETH)`);
  console.log(`  A's balance after:  ${krkBalanceAFinal} KRK (unchanged ✓)`);
  console.log(`  Price impact:       ${((10000n - tokensPerEthB * 10000n / tokensPerEthA) / 100n)}% worse for B`);
  console.log('═══════════════════════════════════════════════════════════');
});
