import { expect, test, type Page } from './fixtures';

// The Wallet section against the mock transport (no backend). The mock seeds a web/native (direct)
// account holding a direct (120) + vk (400) chip segment and a small catalog (two chip-priced values
// and one rouble-priced chip pack — see lib/mock/client.ts), so the compact balance, the split
// storefront, the exchange-confirm dialog (with its store-compliance warning) and the Google Play
// stub are all exercisable without a backend.

async function loginLobby(page: Page): Promise<void> {
  await page.goto('/');
  await page.getByRole('button', { name: /guest/i }).click();
  await expect(page.getByText('Your turn')).toBeVisible();
}

async function openSettings(page: Page): Promise<void> {
  await page.getByRole('button', { name: /Settings/ }).click(); // lobby ⚙️ tab
  await expect(page.locator('.pane')).toHaveCount(1); // let the slide settle
}

async function openWallet(page: Page): Promise<void> {
  await openSettings(page);
  await page.getByRole('button', { name: 'Wallet', exact: true }).click();
  await expect(page.getByTestId('wallet')).toBeVisible();
}

test('wallet: balance, active benefits and the split storefront render for a durable account', async ({ page }) => {
  await loginLobby(page);
  await openWallet(page);

  // The compact balance leads with the context's own (direct/"Web") chips, then the linked vk
  // segment behind its logo.
  const balance = page.getByTestId('balance');
  await expect(balance).toContainText('120');
  await expect(balance).toContainText('400');
  await expect(balance.locator('.plogo')).toHaveCount(1); // the one linked (vk) platform

  // The active benefits (the seeded 5 hints) sit above the store.
  await expect(page.getByRole('heading', { name: 'Active' })).toBeVisible();
  await expect(page.getByTestId('active')).toContainText('Hints: 5');
  await expect(page.getByRole('heading', { name: 'Store' })).toBeVisible();

  // Default tab — Buy chips: one rouble-priced pack + the public offer, and no values.
  await expect(page.locator('[data-kind="pack"]')).toHaveCount(1);
  await expect(page.locator('[data-kind="pack"]')).toContainText('₽');
  await expect(page.locator('[data-kind="pack"]').getByTestId('buy-pack')).toBeEnabled();
  await expect(page.getByTestId('offer')).toContainText('Public offer');
  await expect(page.locator('[data-kind="value"]')).toHaveCount(0);

  // Spend chips tab: the two chip-priced values, exchanged (not bought) with the "Exchange" button.
  await page.getByTestId('tab-spend').click();
  await expect(page.locator('[data-kind="value"]')).toHaveCount(2);
  await expect(page.locator('[data-kind="value"]').first().getByTestId('buy')).toHaveText('Exchange');
});

test('wallet: buying a chip pack opens the provider payment page', async ({ page }) => {
  await loginLobby(page);
  await openWallet(page);

  // The purchase opens the provider's hosted-payment page in a new tab (window.open); capture it.
  await page.evaluate(() => {
    (window as { __opened?: string }).__opened = '';
    window.open = ((u: string) => {
      (window as { __opened?: string }).__opened = u;
      return null;
    }) as typeof window.open;
  });
  await page.locator('[data-kind="pack"]').getByTestId('buy-pack').click();
  await expect
    .poll(() => page.evaluate(() => (window as { __opened?: string }).__opened))
    .toContain('yookassa');
});

test('wallet: the tab sits between Friends and About', async ({ page }) => {
  await loginLobby(page);
  await openSettings(page);
  const labels = await page.locator('.tab .lbl').allInnerTexts();
  const iFriends = labels.indexOf('Friends');
  const iWallet = labels.indexOf('Wallet');
  const iAbout = labels.indexOf('Info');
  expect(iFriends).toBeGreaterThanOrEqual(0);
  expect(iWallet).toBe(iFriends + 1);
  expect(iAbout).toBe(iWallet + 1);
});

test('wallet: a guest has no wallet (nor friends) tab', async ({ page }) => {
  await page.goto('/?guest');
  await page.getByRole('button', { name: /guest/i }).click();
  await expect(page.getByText('Your turn')).toBeVisible();
  await openSettings(page);
  await expect(page.getByRole('button', { name: 'Wallet', exact: true })).toBeHidden();
  await expect(page.getByRole('button', { name: 'Friends', exact: true })).toBeHidden();
});

test('wallet: the Google Play build hides the money purchases behind the RuStore stub', async ({ page }) => {
  await page.goto('/?gp');
  await page.getByRole('button', { name: /guest/i }).click();
  await expect(page.getByText('Your turn')).toBeVisible();
  await openWallet(page);

  // Buy chips: the chip pack is gone; the stub points at the RuStore build.
  await expect(page.getByTestId('gp-stub')).toBeVisible();
  await expect(page.locator('[data-kind="pack"]')).toHaveCount(0);
  // Spending earned chips still works — the values live in the Spend tab.
  await page.getByTestId('tab-spend').click();
  await expect(page.locator('[data-kind="value"]').first().getByTestId('buy')).toBeVisible();
});

test('wallet: the native MVP hides the money purchases behind a neutral note (no store pointer)', async ({ page }) => {
  await page.goto('/?nopay');
  await page.getByRole('button', { name: /guest/i }).click();
  await expect(page.getByText('Your turn')).toBeVisible();
  await openWallet(page);

  // Buy chips: the chip pack is gone; a neutral note shows and — unlike the Google Play build — it
  // carries no RuStore (or any store) pointer.
  await expect(page.getByTestId('purchases-hidden')).toBeVisible();
  await expect(page.getByTestId('gp-stub')).toHaveCount(0);
  await expect(page.locator('[data-kind="pack"]')).toHaveCount(0);
  // Spending earned chips still works — the values live in the Spend tab.
  await page.getByTestId('tab-spend').click();
  await expect(page.locator('[data-kind="value"]').first().getByTestId('buy')).toBeVisible();
});

test('wallet: a web spend that would draw store chips confirms with a warning, then completes', async ({ page }) => {
  await loginLobby(page);
  await openWallet(page);
  await page.getByTestId('tab-spend').click();

  // The 300-chip value drains direct (120) then reaches into vk (180) → a store segment → the confirm
  // dialog carries the cross-platform warning.
  await page.locator('[data-pid="val-noads-30"]').getByTestId('buy').click();
  await expect(page.getByTestId('warn')).toBeVisible();
  await page.getByTestId('spend-confirm').click();
  // The spend applied: the no-ads benefit now shows an end date in the Active section.
  await expect(page.getByTestId('wallet')).toContainText('No ads until');
});

test('wallet: a spend the direct segment covers alone confirms without a warning', async ({ page }) => {
  await loginLobby(page);
  await openWallet(page);
  await page.getByTestId('tab-spend').click();

  // The 100-chip value is covered by the direct segment (120) alone → the confirm dialog shows, but
  // with no cross-platform warning.
  await page.locator('[data-pid="val-hints-50"]').getByTestId('buy').click();
  await expect(page.getByTestId('spend-body')).toBeVisible();
  await expect(page.getByTestId('warn')).toBeHidden();
  await page.getByTestId('spend-confirm').click();
  // The hints benefit rose from 5 to 55.
  await expect(page.getByTestId('wallet')).toContainText('Hints: 55');
});
