/**
 * Test B: Comprehensive Staker Journey (v2)
 * 
 * Tests the full staking flow with three personas:
 * - Marcus (Anvil #3): "the snatcher" - executes snatch operations
 * - Sarah (Anvil #4): "the risk manager" - focuses on P&L and exit
 * - Priya (Anvil #5): "new staker" - fresh staking experience
 * 
 * Prerequisites: Run setup-chain-state.ts to prepare initial positions
 */

import { expect, test } from '@playwright/test';
import { Wallet, ethers } from 'ethers';
import { createWalletContext } from '../../setup/wallet-provider';
import { getStackConfig, validateStackHealthy } from '../../setup/stack';
import {
  createPersonaFeedback,
  addFeedbackStep,
  writePersonaFeedback,
  resetChainState,
  connectWallet,
  type PersonaFeedback,
} from './helpers';
import { mkdirSync } from 'fs';
import { join } from 'path';
import { execSync } from 'child_process';

const STACK_CONFIG = getStackConfig();
const STACK_RPC_URL = STACK_CONFIG.rpcUrl;
const STAKE_PAGE_URL = `${STACK_CONFIG.webAppUrl}/app/stake`;

// Anvil test account keys
const MARCUS_KEY = '0x7c852118294e51e653712a81e05800f419141751be58f605c371e15141b007a6'; // Anvil #3
const SARAH_KEY = '0x47e179ec197488593b187f80a00eb0da91f1b9d0b13f8733639f19c30a34926a'; // Anvil #4
const PRIYA_KEY = '0x8b3a350cf5c34c9194ca85829a2df0ec3153be0318b5e2d3348e872092edffba'; // Anvil #5

test.describe('Test B: Staker Journey v2', () => {
  test.beforeAll(async () => {
    console.log('[SETUP] Validating stack health...');
    await validateStackHealthy(STACK_CONFIG);
    
    console.log('[SETUP] Running chain state setup script...');
    try {
      execSync('npx tsx tests/e2e/usertest/setup-chain-state.ts', {
        cwd: process.cwd(),
        stdio: 'inherit',
      });
    } catch (error) {
      console.error('[SETUP] Chain state setup failed:', error);
      throw error;
    }

    console.log('[SETUP] Saving initial snapshot for persona resets...');
    await resetChainState(STACK_RPC_URL);
  });

  test.describe.serial('Marcus - "the snatcher"', () => {
    let feedback: PersonaFeedback;
    const accountKey = MARCUS_KEY;
    const accountAddr = new Wallet(accountKey).address;

    test.beforeAll(() => {
      feedback = createPersonaFeedback('marcus-v2', 'B', 'staker');
    });

    test('Marcus connects wallet and navigates to stake page', async ({ browser }) => {
      const context = await createWalletContext(browser, {
        privateKey: accountKey,
        rpcUrl: STACK_RPC_URL,
      });

      const page = await context.newPage();
      const observations: string[] = [];

      try {
        observations.push('Navigating to stake page...');
        await page.goto(STAKE_PAGE_URL, { waitUntil: 'domcontentloaded' });
        // eslint-disable-next-line no-restricted-syntax -- waitForTimeout: no event source exists for animation settling, wallet connector UI transitions, and debounced state updates in user-simulation tests. See AGENTS.md #Engineering Principles.
        await page.waitForTimeout(3_000);

        // Connect wallet
        observations.push('Connecting wallet...');
        await connectWallet(page);
        // eslint-disable-next-line no-restricted-syntax -- waitForTimeout: no event source exists for animation settling, wallet connector UI transitions, and debounced state updates in user-simulation tests. See AGENTS.md #Engineering Principles.
        await page.waitForTimeout(2_000);

        const walletDisplay = page.getByText(/0x[a-fA-F0-9]{4}/i).first();
        const isConnected = await walletDisplay.isVisible().catch(() => false);
        
        if (isConnected) {
          observations.push('✓ Wallet connected successfully');
        } else {
          observations.push('✗ Wallet connection failed');
          feedback.overall.friction.push('Wallet connection failed');
        }

        // Screenshot
        const screenshotDir = join('test-results', 'usertest', 'marcus-v2');
        mkdirSync(screenshotDir, { recursive: true });
        const screenshotPath = join(screenshotDir, `01-wallet-connected-${Date.now()}.png`);
        await page.screenshot({ path: screenshotPath, fullPage: true });

        addFeedbackStep(feedback, 'connect-wallet', observations, screenshotPath);

      } finally {
        await context.close();
      }
    });

    test('Marcus verifies his existing position is visible with P&L', async ({ browser }) => {
      const context = await createWalletContext(browser, {
        privateKey: accountKey,
        rpcUrl: STACK_RPC_URL,
      });

      const page = await context.newPage();
      const observations: string[] = [];

      try {
        await page.goto(STAKE_PAGE_URL, { waitUntil: 'domcontentloaded' });
        // eslint-disable-next-line no-restricted-syntax -- waitForTimeout: no event source exists for animation settling, wallet connector UI transitions, and debounced state updates in user-simulation tests. See AGENTS.md #Engineering Principles.
        await page.waitForTimeout(3_000);
        await connectWallet(page);
        // eslint-disable-next-line no-restricted-syntax -- waitForTimeout: no event source exists for animation settling, wallet connector UI transitions, and debounced state updates in user-simulation tests. See AGENTS.md #Engineering Principles.
        await page.waitForTimeout(3_000);

        observations.push('Looking for my existing position created in setup...');

        // Look for active positions section
        const activePositions = page.locator('.active-positions-wrapper, .f-collapse-active, [class*="position"]');
        const hasPositions = await activePositions.isVisible({ timeout: 10_000 }).catch(() => false);

        if (hasPositions) {
          const positionCount = await page.locator('.f-collapse-active').count();
          observations.push(`✓ Found ${positionCount} active position(s)`);

          // Check for P&L display
          const hasPnL = await page.locator('.pnl-metrics, .pnl-line1, text=/gross|tax|net/i').isVisible().catch(() => false);
          if (hasPnL) {
            observations.push('✓ P&L metrics visible (Gross/Tax/Net)');
          } else {
            observations.push('⚠ P&L metrics not visible');
            feedback.overall.friction.push('Position P&L not displayed');
          }

          // Check for position details
          const hasDetails = await page.locator('text=/initial stake|tax rate|time held/i').isVisible().catch(() => false);
          if (hasDetails) {
            observations.push('✓ Position details displayed');
          } else {
            observations.push('⚠ Position details incomplete');
          }

        } else {
          observations.push('✗ No active positions found - setup may have failed');
          feedback.overall.friction.push('Position created in setup not visible');
        }

        // Screenshot
        const screenshotDir = join('test-results', 'usertest', 'marcus-v2');
        const screenshotPath = join(screenshotDir, `02-existing-position-${Date.now()}.png`);
        await page.screenshot({ path: screenshotPath, fullPage: true });

        addFeedbackStep(feedback, 'verify-existing-position', observations, screenshotPath);

      } finally {
        await context.close();
      }
    });

    test('Marcus finds Sarah\'s position and executes snatch', async ({ browser }) => {
      const context = await createWalletContext(browser, {
        privateKey: accountKey,
        rpcUrl: STACK_RPC_URL,
      });

      const page = await context.newPage();
      const observations: string[] = [];

      try {
        await page.goto(STAKE_PAGE_URL, { waitUntil: 'domcontentloaded' });
        // eslint-disable-next-line no-restricted-syntax -- waitForTimeout: no event source exists for animation settling, wallet connector UI transitions, and debounced state updates in user-simulation tests. See AGENTS.md #Engineering Principles.
        await page.waitForTimeout(3_000);
        await connectWallet(page);
        // eslint-disable-next-line no-restricted-syntax -- waitForTimeout: no event source exists for animation settling, wallet connector UI transitions, and debounced state updates in user-simulation tests. See AGENTS.md #Engineering Principles.
        await page.waitForTimeout(3_000);

        observations.push('Looking for other positions with lower tax rates to snatch...');

        // Check if we can see other positions (not just our own)
        const allPositions = await page.locator('.f-collapse-active, [class*="position-card"]').count();
        observations.push(`Found ${allPositions} total positions visible`);

        // Fill stake form to snatch
        observations.push('Filling snatch form: amount + higher tax rate...');
        
        const amountInput = page.getByLabel('Staking Amount').or(page.locator('input[type="number"]').first());
        await amountInput.waitFor({ state: 'visible', timeout: 10_000 });
        await amountInput.fill('200'); // Amount to snatch
        // eslint-disable-next-line no-restricted-syntax -- waitForTimeout: no event source exists for animation settling, wallet connector UI transitions, and debounced state updates in user-simulation tests. See AGENTS.md #Engineering Principles.
        await page.waitForTimeout(500);

        // Select HIGHER tax rate than victim (Sarah has index 10, so use index 12+)
        const taxSelect = page.locator('select.tax-select').or(page.getByRole('combobox', { name: /tax/i }).first());
        await taxSelect.selectOption({ index: 12 }); // Higher than Sarah's medium tax
        // eslint-disable-next-line no-restricted-syntax -- waitForTimeout: no event source exists for animation settling, wallet connector UI transitions, and debounced state updates in user-simulation tests. See AGENTS.md #Engineering Principles.
        await page.waitForTimeout(1_000);

        // Check button text
        const stakeButton = page.getByRole('button', { name: /snatch and stake|stake/i }).first();
        const buttonText = await stakeButton.textContent().catch(() => '');
        
        if (buttonText?.toLowerCase().includes('snatch')) {
          observations.push('✓ Button shows "Snatch and Stake" - clear action');
          
          // Check for snatch summary
          const summary = page.locator('.stake-summary, text=/snatch/i');
          const hasSummary = await summary.isVisible().catch(() => false);
          if (hasSummary) {
            observations.push('✓ Snatch summary visible');
          }

          // Screenshot before snatch
          const screenshotDir = join('test-results', 'usertest', 'marcus-v2');
          const preSnatchPath = join(screenshotDir, `03-pre-snatch-${Date.now()}.png`);
          await page.screenshot({ path: preSnatchPath, fullPage: true });

          // Execute snatch
          observations.push('Executing snatch transaction...');
          await stakeButton.click();
          // eslint-disable-next-line no-restricted-syntax -- waitForTimeout: no event source exists for animation settling, wallet connector UI transitions, and debounced state updates in user-simulation tests. See AGENTS.md #Engineering Principles.
          await page.waitForTimeout(2_000);

          // Wait for transaction completion
          try {
            await page.getByRole('button', { name: /^(snatch and stake|stake)$/i }).waitFor({ 
              state: 'visible',
              timeout: 30_000 
            });
            observations.push('✓ Snatch transaction completed');
          } catch (error) {
            observations.push('⚠ Snatch transaction may be pending');
          }

          // eslint-disable-next-line no-restricted-syntax -- waitForTimeout: no event source exists for animation settling, wallet connector UI transitions, and debounced state updates in user-simulation tests. See AGENTS.md #Engineering Principles.
          await page.waitForTimeout(3_000);

          // Verify snatched position appears
          const newPositionCount = await page.locator('.f-collapse-active').count();
          observations.push(`Now have ${newPositionCount} active position(s)`);

        } else {
          observations.push('Button shows "Stake" - may not be snatching or no targets available');
        }

        // Screenshot after snatch
        const screenshotDir = join('test-results', 'usertest', 'marcus-v2');
        const postSnatchPath = join(screenshotDir, `04-post-snatch-${Date.now()}.png`);
        await page.screenshot({ path: postSnatchPath, fullPage: true });

        addFeedbackStep(feedback, 'execute-snatch', observations, postSnatchPath);

      } finally {
        await context.close();
        writePersonaFeedback(feedback);
      }
    });
  });

  test.describe.serial('Sarah - "the risk manager"', () => {
    let feedback: PersonaFeedback;
    const accountKey = SARAH_KEY;
    const accountAddr = new Wallet(accountKey).address;

    test.beforeAll(() => {
      feedback = createPersonaFeedback('sarah-v2', 'B', 'staker');
    });

    test('Sarah connects and views her position', async ({ browser }) => {
      const context = await createWalletContext(browser, {
        privateKey: accountKey,
        rpcUrl: STACK_RPC_URL,
      });

      const page = await context.newPage();
      const observations: string[] = [];

      try {
        observations.push('Sarah connecting to view her staked position...');
        await page.goto(STAKE_PAGE_URL, { waitUntil: 'domcontentloaded' });
        // eslint-disable-next-line no-restricted-syntax -- waitForTimeout: no event source exists for animation settling, wallet connector UI transitions, and debounced state updates in user-simulation tests. See AGENTS.md #Engineering Principles.
        await page.waitForTimeout(3_000);

        await connectWallet(page);
        // eslint-disable-next-line no-restricted-syntax -- waitForTimeout: no event source exists for animation settling, wallet connector UI transitions, and debounced state updates in user-simulation tests. See AGENTS.md #Engineering Principles.
        await page.waitForTimeout(3_000);

        // Look for position
        const hasPosition = await page.locator('.f-collapse-active, [class*="position"]').isVisible().catch(() => false);
        
        if (hasPosition) {
          observations.push('✓ Position visible');
        } else {
          observations.push('✗ Position not found - may have been snatched');
        }

        // Screenshot
        const screenshotDir = join('test-results', 'usertest', 'sarah-v2');
        mkdirSync(screenshotDir, { recursive: true });
        const screenshotPath = join(screenshotDir, `01-view-position-${Date.now()}.png`);
        await page.screenshot({ path: screenshotPath, fullPage: true });

        addFeedbackStep(feedback, 'view-position', observations, screenshotPath);

      } finally {
        await context.close();
      }
    });

    test('Sarah checks P&L display (gross return, tax cost, net return)', async ({ browser }) => {
      const context = await createWalletContext(browser, {
        privateKey: accountKey,
        rpcUrl: STACK_RPC_URL,
      });

      const page = await context.newPage();
      const observations: string[] = [];

      try {
        await page.goto(STAKE_PAGE_URL, { waitUntil: 'domcontentloaded' });
        // eslint-disable-next-line no-restricted-syntax -- waitForTimeout: no event source exists for animation settling, wallet connector UI transitions, and debounced state updates in user-simulation tests. See AGENTS.md #Engineering Principles.
        await page.waitForTimeout(3_000);
        await connectWallet(page);
        // eslint-disable-next-line no-restricted-syntax -- waitForTimeout: no event source exists for animation settling, wallet connector UI transitions, and debounced state updates in user-simulation tests. See AGENTS.md #Engineering Principles.
        await page.waitForTimeout(3_000);

        observations.push('Analyzing P&L metrics for risk assessment...');

        // Check for P&L breakdown
        const pnlLine = page.locator('.pnl-line1, text=/gross.*tax.*net/i');
        const hasPnL = await pnlLine.isVisible().catch(() => false);

        if (hasPnL) {
          const pnlText = await pnlLine.textContent().catch(() => '');
          observations.push(`✓ P&L display found: ${pnlText}`);

          // Check for positive/negative indicators
          const isPositive = await page.locator('.pnl-positive').isVisible().catch(() => false);
          const isNegative = await page.locator('.pnl-negative').isVisible().catch(() => false);

          if (isPositive) {
            observations.push('✓ Net return is positive (green)');
          } else if (isNegative) {
            observations.push('⚠ Net return is negative (red)');
          }

        } else {
          observations.push('✗ P&L metrics not visible');
          feedback.overall.friction.push('P&L display missing');
        }

        // Check for time held
        const timeHeld = page.locator('.pnl-line2, text=/held.*d.*h/i');
        const hasTimeHeld = await timeHeld.isVisible().catch(() => false);
        
        if (hasTimeHeld) {
          const timeText = await timeHeld.textContent().catch(() => '');
          observations.push(`✓ Time held displayed: ${timeText}`);
        } else {
          observations.push('⚠ Time held not visible');
        }

        // Screenshot
        const screenshotDir = join('test-results', 'usertest', 'sarah-v2');
        const screenshotPath = join(screenshotDir, `02-pnl-analysis-${Date.now()}.png`);
        await page.screenshot({ path: screenshotPath, fullPage: true });

        addFeedbackStep(feedback, 'check-pnl', observations, screenshotPath);

      } finally {
        await context.close();
      }
    });

    test('Sarah executes exitPosition to recover her KRK', async ({ browser }) => {
      const context = await createWalletContext(browser, {
        privateKey: accountKey,
        rpcUrl: STACK_RPC_URL,
      });

      const page = await context.newPage();
      const observations: string[] = [];

      try {
        await page.goto(STAKE_PAGE_URL, { waitUntil: 'domcontentloaded' });
        // eslint-disable-next-line no-restricted-syntax -- waitForTimeout: no event source exists for animation settling, wallet connector UI transitions, and debounced state updates in user-simulation tests. See AGENTS.md #Engineering Principles.
        await page.waitForTimeout(3_000);
        await connectWallet(page);
        // eslint-disable-next-line no-restricted-syntax -- waitForTimeout: no event source exists for animation settling, wallet connector UI transitions, and debounced state updates in user-simulation tests. See AGENTS.md #Engineering Principles.
        await page.waitForTimeout(3_000);

        observations.push('Exiting position to recover KRK...');

        // Find position and expand it
        const position = page.locator('.f-collapse-active').first();
        const hasPosition = await position.isVisible().catch(() => false);

        if (!hasPosition) {
          observations.push('✗ No position to exit - may have been snatched already');
          feedback.overall.friction.push('Position disappeared before exit');
          
          const screenshotDir = join('test-results', 'usertest', 'sarah-v2');
          const screenshotPath = join(screenshotDir, `03-no-position-${Date.now()}.png`);
          await page.screenshot({ path: screenshotPath, fullPage: true });
          
          addFeedbackStep(feedback, 'exit-position', observations, screenshotPath);
          await context.close();
          return;
        }

        // Expand position to see actions
        await position.click();
        // eslint-disable-next-line no-restricted-syntax -- waitForTimeout: no event source exists for animation settling, wallet connector UI transitions, and debounced state updates in user-simulation tests. See AGENTS.md #Engineering Principles.
        await page.waitForTimeout(1_000);

        // Look for Unstake/Exit button
        const exitButton = position.getByRole('button', { name: /unstake|exit/i });
        const hasExitButton = await exitButton.isVisible().catch(() => false);

        if (hasExitButton) {
          observations.push('✓ Exit button found');

          // Screenshot before exit
          const screenshotDir = join('test-results', 'usertest', 'sarah-v2');
          const preExitPath = join(screenshotDir, `03-pre-exit-${Date.now()}.png`);
          await page.screenshot({ path: preExitPath, fullPage: true });

          // Click exit
          await exitButton.click();
          // eslint-disable-next-line no-restricted-syntax -- waitForTimeout: no event source exists for animation settling, wallet connector UI transitions, and debounced state updates in user-simulation tests. See AGENTS.md #Engineering Principles.
          await page.waitForTimeout(2_000);

          // Wait for transaction
          try {
            // eslint-disable-next-line no-restricted-syntax -- waitForTimeout: no event source exists for animation settling, wallet connector UI transitions, and debounced state updates in user-simulation tests. See AGENTS.md #Engineering Principles.
            await page.waitForTimeout(5_000); // Give time for tx confirmation
            observations.push('✓ Exit transaction submitted');
          } catch (error) {
            observations.push('⚠ Exit transaction may be pending');
          }

          // Verify position is gone
          // eslint-disable-next-line no-restricted-syntax -- waitForTimeout: no event source exists for animation settling, wallet connector UI transitions, and debounced state updates in user-simulation tests. See AGENTS.md #Engineering Principles.
          await page.waitForTimeout(3_000);
          const stillVisible = await position.isVisible().catch(() => false);
          
          if (!stillVisible) {
            observations.push('✓ Position removed from Active Positions');
          } else {
            observations.push('⚠ Position still visible after exit');
          }

          // Screenshot after exit
          const postExitPath = join(screenshotDir, `04-post-exit-${Date.now()}.png`);
          await page.screenshot({ path: postExitPath, fullPage: true });

        } else {
          observations.push('✗ Exit button not found');
          feedback.overall.friction.push('Exit mechanism not accessible');
        }

        addFeedbackStep(feedback, 'exit-position', observations);

      } finally {
        await context.close();
        writePersonaFeedback(feedback);
      }
    });
  });

  test.describe.serial('Priya - "new staker"', () => {
    let feedback: PersonaFeedback;
    const accountKey = PRIYA_KEY;
    const accountAddr = new Wallet(accountKey).address;

    test.beforeAll(() => {
      feedback = createPersonaFeedback('priya-v2', 'B', 'staker');
    });

    test('Priya connects wallet (fresh staker, no positions)', async ({ browser }) => {
      const context = await createWalletContext(browser, {
        privateKey: accountKey,
        rpcUrl: STACK_RPC_URL,
      });

      const page = await context.newPage();
      const observations: string[] = [];

      try {
        observations.push('Priya (fresh staker) connecting wallet...');
        await page.goto(STAKE_PAGE_URL, { waitUntil: 'domcontentloaded' });
        // eslint-disable-next-line no-restricted-syntax -- waitForTimeout: no event source exists for animation settling, wallet connector UI transitions, and debounced state updates in user-simulation tests. See AGENTS.md #Engineering Principles.
        await page.waitForTimeout(3_000);

        await connectWallet(page);
        // eslint-disable-next-line no-restricted-syntax -- waitForTimeout: no event source exists for animation settling, wallet connector UI transitions, and debounced state updates in user-simulation tests. See AGENTS.md #Engineering Principles.
        await page.waitForTimeout(3_000);

        // Verify no existing positions
        const hasPositions = await page.locator('.f-collapse-active').isVisible({ timeout: 5_000 }).catch(() => false);
        
        if (!hasPositions) {
          observations.push('✓ No existing positions (fresh staker)');
        } else {
          observations.push('⚠ Found existing positions - test may be contaminated');
        }

        // Screenshot
        const screenshotDir = join('test-results', 'usertest', 'priya-v2');
        mkdirSync(screenshotDir, { recursive: true });
        const screenshotPath = join(screenshotDir, `01-fresh-state-${Date.now()}.png`);
        await page.screenshot({ path: screenshotPath, fullPage: true });

        addFeedbackStep(feedback, 'connect-wallet', observations, screenshotPath);

      } finally {
        await context.close();
      }
    });

    test('Priya fills staking amount using selectors from reference', async ({ browser }) => {
      const context = await createWalletContext(browser, {
        privateKey: accountKey,
        rpcUrl: STACK_RPC_URL,
      });

      const page = await context.newPage();
      const observations: string[] = [];

      try {
        await page.goto(STAKE_PAGE_URL, { waitUntil: 'domcontentloaded' });
        // eslint-disable-next-line no-restricted-syntax -- waitForTimeout: no event source exists for animation settling, wallet connector UI transitions, and debounced state updates in user-simulation tests. See AGENTS.md #Engineering Principles.
        await page.waitForTimeout(3_000);
        await connectWallet(page);
        // eslint-disable-next-line no-restricted-syntax -- waitForTimeout: no event source exists for animation settling, wallet connector UI transitions, and debounced state updates in user-simulation tests. See AGENTS.md #Engineering Principles.
        await page.waitForTimeout(3_000);

        observations.push('Filling staking form as a new user...');

        // Use selector from reference doc: page.getByLabel('Staking Amount')
        const amountInput = page.getByLabel('Staking Amount');
        const hasInput = await amountInput.isVisible({ timeout: 10_000 }).catch(() => false);

        if (hasInput) {
          observations.push('✓ Staking Amount input found');
          await amountInput.fill('100');
          // eslint-disable-next-line no-restricted-syntax -- waitForTimeout: no event source exists for animation settling, wallet connector UI transitions, and debounced state updates in user-simulation tests. See AGENTS.md #Engineering Principles.
          await page.waitForTimeout(500);
          observations.push('✓ Filled amount: 100 KRK');
        } else {
          observations.push('✗ Staking Amount input not found');
          feedback.overall.friction.push('Staking amount input not accessible');
        }

        // Screenshot
        const screenshotDir = join('test-results', 'usertest', 'priya-v2');
        const screenshotPath = join(screenshotDir, `02-amount-filled-${Date.now()}.png`);
        await page.screenshot({ path: screenshotPath, fullPage: true });

        addFeedbackStep(feedback, 'fill-amount', observations, screenshotPath);

      } finally {
        await context.close();
      }
    });

    test('Priya selects tax rate via dropdown', async ({ browser }) => {
      const context = await createWalletContext(browser, {
        privateKey: accountKey,
        rpcUrl: STACK_RPC_URL,
      });

      const page = await context.newPage();
      const observations: string[] = [];

      try {
        await page.goto(STAKE_PAGE_URL, { waitUntil: 'domcontentloaded' });
        // eslint-disable-next-line no-restricted-syntax -- waitForTimeout: no event source exists for animation settling, wallet connector UI transitions, and debounced state updates in user-simulation tests. See AGENTS.md #Engineering Principles.
        await page.waitForTimeout(3_000);
        await connectWallet(page);
        // eslint-disable-next-line no-restricted-syntax -- waitForTimeout: no event source exists for animation settling, wallet connector UI transitions, and debounced state updates in user-simulation tests. See AGENTS.md #Engineering Principles.
        await page.waitForTimeout(3_000);

        // Fill amount first
        const amountInput = page.getByLabel('Staking Amount');
        await amountInput.fill('100');
        // eslint-disable-next-line no-restricted-syntax -- waitForTimeout: no event source exists for animation settling, wallet connector UI transitions, and debounced state updates in user-simulation tests. See AGENTS.md #Engineering Principles.
        await page.waitForTimeout(500);

        observations.push('Selecting tax rate...');

        // Use selector from reference: page.locator('select.tax-select')
        const taxSelect = page.locator('select.tax-select');
        const hasTaxSelect = await taxSelect.isVisible({ timeout: 10_000 }).catch(() => false);

        if (hasTaxSelect) {
          observations.push('✓ Tax rate selector found');
          
          // Select a mid-range tax rate (index 5)
          await taxSelect.selectOption({ index: 5 });
          // eslint-disable-next-line no-restricted-syntax -- waitForTimeout: no event source exists for animation settling, wallet connector UI transitions, and debounced state updates in user-simulation tests. See AGENTS.md #Engineering Principles.
          await page.waitForTimeout(500);
          
          const selectedValue = await taxSelect.inputValue();
          observations.push(`✓ Selected tax rate index: ${selectedValue}`);

        } else {
          observations.push('✗ Tax rate selector not found');
          feedback.overall.friction.push('Tax rate selector not accessible');
        }

        // Screenshot
        const screenshotDir = join('test-results', 'usertest', 'priya-v2');
        const screenshotPath = join(screenshotDir, `03-tax-selected-${Date.now()}.png`);
        await page.screenshot({ path: screenshotPath, fullPage: true });

        addFeedbackStep(feedback, 'select-tax-rate', observations, screenshotPath);

      } finally {
        await context.close();
      }
    });

    test('Priya clicks Snatch and Stake button and handles permit signing', async ({ browser }) => {
      const context = await createWalletContext(browser, {
        privateKey: accountKey,
        rpcUrl: STACK_RPC_URL,
      });

      const page = await context.newPage();
      const observations: string[] = [];

      try {
        await page.goto(STAKE_PAGE_URL, { waitUntil: 'domcontentloaded' });
        // eslint-disable-next-line no-restricted-syntax -- waitForTimeout: no event source exists for animation settling, wallet connector UI transitions, and debounced state updates in user-simulation tests. See AGENTS.md #Engineering Principles.
        await page.waitForTimeout(3_000);
        await connectWallet(page);
        // eslint-disable-next-line no-restricted-syntax -- waitForTimeout: no event source exists for animation settling, wallet connector UI transitions, and debounced state updates in user-simulation tests. See AGENTS.md #Engineering Principles.
        await page.waitForTimeout(3_000);

        observations.push('Completing stake form and executing transaction...');

        // Fill form
        const amountInput = page.getByLabel('Staking Amount');
        await amountInput.fill('100');
        // eslint-disable-next-line no-restricted-syntax -- waitForTimeout: no event source exists for animation settling, wallet connector UI transitions, and debounced state updates in user-simulation tests. See AGENTS.md #Engineering Principles.
        await page.waitForTimeout(500);

        const taxSelect = page.locator('select.tax-select');
        await taxSelect.selectOption({ index: 5 });
        // eslint-disable-next-line no-restricted-syntax -- waitForTimeout: no event source exists for animation settling, wallet connector UI transitions, and debounced state updates in user-simulation tests. See AGENTS.md #Engineering Principles.
        await page.waitForTimeout(1_000);

        // Find stake button using reference selector
        const stakeButton = page.getByRole('button', { name: /snatch and stake/i });
        const hasButton = await stakeButton.isVisible({ timeout: 10_000 }).catch(() => false);

        if (hasButton) {
          const buttonText = await stakeButton.textContent().catch(() => '');
          observations.push(`✓ Stake button found: "${buttonText}"`);

          // Check if enabled
          const isEnabled = await stakeButton.isEnabled().catch(() => false);
          if (!isEnabled) {
            observations.push('⚠ Button is disabled - checking for errors...');
            
            // Check for error messages
            const errorMessages = await page.locator('text=/insufficient|too low|invalid/i').allTextContents();
            if (errorMessages.length > 0) {
              observations.push(`✗ Errors: ${errorMessages.join(', ')}`);
              feedback.overall.friction.push('Stake button disabled with errors');
            }
          } else {
            observations.push('✓ Button is enabled');

            // Screenshot before stake
            const screenshotDir = join('test-results', 'usertest', 'priya-v2');
            const preStakePath = join(screenshotDir, `04-pre-stake-${Date.now()}.png`);
            await page.screenshot({ path: preStakePath, fullPage: true });

            // Click stake button
            observations.push('Clicking stake button...');
            await stakeButton.click();
            // eslint-disable-next-line no-restricted-syntax -- waitForTimeout: no event source exists for animation settling, wallet connector UI transitions, and debounced state updates in user-simulation tests. See AGENTS.md #Engineering Principles.
            await page.waitForTimeout(2_000);

            // The wallet provider auto-signs, but check for transaction state
            observations.push('✓ Permit signing handled by wallet provider (EIP-2612)');
            
            // Wait for transaction completion
            try {
              // eslint-disable-next-line no-restricted-syntax -- waitForTimeout: no event source exists for animation settling, wallet connector UI transitions, and debounced state updates in user-simulation tests. See AGENTS.md #Engineering Principles.
              await page.waitForTimeout(5_000);
              observations.push('✓ Transaction submitted');
            } catch (error) {
              observations.push('⚠ Transaction may be pending');
            }

            // eslint-disable-next-line no-restricted-syntax -- waitForTimeout: no event source exists for animation settling, wallet connector UI transitions, and debounced state updates in user-simulation tests. See AGENTS.md #Engineering Principles.
            await page.waitForTimeout(3_000);

            // Screenshot after stake
            const postStakePath = join(screenshotDir, `05-post-stake-${Date.now()}.png`);
            await page.screenshot({ path: postStakePath, fullPage: true });
          }

        } else {
          observations.push('✗ Stake button not found');
          feedback.overall.friction.push('Stake button not accessible');
        }

        addFeedbackStep(feedback, 'execute-stake', observations);

      } finally {
        await context.close();
      }
    });

    test('Priya verifies position appears in Active Positions', async ({ browser }) => {
      const context = await createWalletContext(browser, {
        privateKey: accountKey,
        rpcUrl: STACK_RPC_URL,
      });

      const page = await context.newPage();
      const observations: string[] = [];

      try {
        await page.goto(STAKE_PAGE_URL, { waitUntil: 'domcontentloaded' });
        // eslint-disable-next-line no-restricted-syntax -- waitForTimeout: no event source exists for animation settling, wallet connector UI transitions, and debounced state updates in user-simulation tests. See AGENTS.md #Engineering Principles.
        await page.waitForTimeout(3_000);
        await connectWallet(page);
        // eslint-disable-next-line no-restricted-syntax -- waitForTimeout: no event source exists for animation settling, wallet connector UI transitions, and debounced state updates in user-simulation tests. See AGENTS.md #Engineering Principles.
        await page.waitForTimeout(3_000);

        observations.push('Checking for new position in Active Positions...');

        // Look for active positions wrapper (from reference)
        const activePositionsWrapper = page.locator('.active-positions-wrapper');
        const hasWrapper = await activePositionsWrapper.isVisible({ timeout: 10_000 }).catch(() => false);

        if (hasWrapper) {
          observations.push('✓ Active Positions section found');

          // Count positions
          const positionCount = await page.locator('.f-collapse-active').count();
          
          if (positionCount > 0) {
            observations.push(`✓ Found ${positionCount} active position(s)`);
            feedback.overall.wouldStake = true;
            feedback.overall.wouldReturn = true;
          } else {
            observations.push('⚠ No positions visible - stake may have failed');
            feedback.overall.wouldStake = false;
          }

        } else {
          observations.push('✗ Active Positions section not found');
          feedback.overall.friction.push('Active Positions not visible after stake');
        }

        // Final screenshot
        const screenshotDir = join('test-results', 'usertest', 'priya-v2');
        const screenshotPath = join(screenshotDir, `06-final-state-${Date.now()}.png`);
        await page.screenshot({ path: screenshotPath, fullPage: true });

        addFeedbackStep(feedback, 'verify-position', observations, screenshotPath);

        // Priya's verdict
        observations.push(`Priya verdict: ${feedback.overall.wouldStake ? 'Successful first stake' : 'Stake failed or unclear'}`);

      } finally {
        await context.close();
        writePersonaFeedback(feedback);
      }
    });
  });
});
