import AxeBuilder from '@axe-core/playwright';
import { expect } from '@playwright/test';

import { parallelWorker as test } from '../fixtures/test.js';

test.describe('App shell', () => {
  test('App renders', async ({ page, conductor }) => {
    const app = await conductor.open();

    await expect(app.getByRole('tabpanel', { name: 'Keywords' })).toBeVisible();
    await page.locator('[role="dialog"] button[aria-label="Close"]').click();
    await expect(page.locator('#extensionPortalContainer')).not.toBeVisible();
  });

  test('Axe accessibility scan', async ({ page, conductor }) => {
    const app = await conductor.open();

    const containerAccessibilityScanResults = await new AxeBuilder({ page })
      .include('#extensionPortalContainer')
      .analyze();
    expect(containerAccessibilityScanResults.violations).toEqual([]);
    const tabs = await app.getByRole('tablist').getByRole('tab').all();
    await conductor.initializeKeywordsAndCompetitorUrls(app);

    for (const tab of tabs) {
      await tab.click();
      const tabId = tab.getAttribute('id');
      await app.getByRole('tabpanel').locator(`[aria-labelledby="${tabId}"]`).isVisible();
      const accessibilityScanResults = await new AxeBuilder({ page })
        .include('#extensionPortalContainer')
        .analyze();

      // @todo this is a known contrast issue with the buttons in the design system.
      const filteredViolations = accessibilityScanResults.violations.filter(
        (violation) =>
          !(
            violation.id === 'color-contrast' &&
            violation.nodes.some(
              (node) => node.target.includes('.loading') || node.target.includes('.tag'),
            )
          ),
      );

      expect(filteredViolations).toEqual([]);
    }
  });

  test('Tabs are usable', async ({ page, conductor }) => {
    const app = await conductor.open();
    await expect(page.locator('[role="dialog"] button[aria-label="Close"]')).toBeFocused();

    // @todo #extensionPortalContainer is able to get focus in firefox but not in chromium.
    // It shouldn't be able to get focus, this needs fixing upstream and then the below can be
    // removed..
    await app.getByRole('tab', { name: 'Keywords' }).click();

    await expect(app.getByRole('tabpanel', { name: 'Keywords' })).toBeVisible();
    await expect(app.getByRole('tabpanel').filter({ visible: true })).toHaveCount(1);

    // First tab.
    // Uncomment the below when the above todo is done.
    //await page.keyboard.press('Tab');
    await expect(app.getByRole('tablist')).toMatchAriaSnapshot(`
      - tablist:
        - tab "Keywords" [selected]
    `);
    await expect(app.getByRole('tabpanel', { name: 'Keywords' })).toBeVisible();
    await expect(app.getByRole('tabpanel').filter({ visible: true })).toHaveCount(1);

    // Second tab.
    await page.keyboard.press('ArrowRight');
    await expect(app.getByRole('tabpanel', { name: 'Competitors' })).toBeVisible();
    await expect(app.getByRole('tabpanel').filter({ visible: true })).toHaveCount(1);
    await expect(app.getByRole('tablist')).toMatchAriaSnapshot(`
      - tablist:
        - tab "Keywords"
        - tab "Competitors" [selected]
        - tab "Content outline"
    `);

    // Third tab.
    await page.keyboard.press('ArrowRight');
    await expect(app.getByRole('tablist')).toMatchAriaSnapshot(`
      - tablist:
        - tab "Keywords"
        - tab "Competitors"
        - tab "Guidance" [selected]
        - tab "Content outline"
    `);
    await expect(app.getByRole('tabpanel', { name: 'Guidance' })).toBeVisible();
    await expect(app.getByRole('tabpanel').filter({ visible: true })).toHaveCount(1);

    // Forth tab.
    await page.keyboard.press('ArrowRight');
    await expect(app.getByRole('tablist')).toMatchAriaSnapshot(`
      - tablist:
        - tab "Keywords"
        - tab "Competitors"
        - tab "Content outline" [selected]
    `);
    await expect(app.getByRole('tabpanel', { name: 'Content outline' })).toBeVisible();
    await expect(app.getByRole('tabpanel').filter({ visible: true })).toHaveCount(1);

    // Wrap around.
    await page.keyboard.press('ArrowRight');
    await expect(app.getByRole('tablist')).toMatchAriaSnapshot(`
      - tablist:
        - tab "Keywords" [selected]
        - tab "Competitors"
        - tab "Content outline"
    `);
    await expect(app.getByRole('tabpanel', { name: 'Keywords' })).toBeVisible();

    // Wrap around.
    await page.keyboard.press('ArrowLeft');
    await expect(app.getByRole('tablist')).toMatchAriaSnapshot(`
      - tablist:
        - tab "Keywords"
        - tab "Competitors"
        - tab "Content outline" [selected]
    `);
    await page.keyboard.press('ArrowLeft');
    await expect(app.getByRole('tablist')).toMatchAriaSnapshot(`
      - tablist:
        - tab "Keywords"
        - tab "Competitors"
        - tab "Guidance" [selected]
        - tab "Content outline"
    `);
    await page.keyboard.press('ArrowLeft');
    await expect(app.getByRole('tablist')).toMatchAriaSnapshot(`
      - tablist:
        - tab "Keywords"
        - tab "Competitors" [selected]
        - tab "Content outline"
    `);

    // Up and down arrow.
    await page.keyboard.press('ArrowUp');
    await expect(app.getByRole('tablist')).toMatchAriaSnapshot(`
      - tablist:
        - tab "Keywords" [selected]
        - tab "Competitors"
        - tab "Content outline"
    `);
    await page.keyboard.press('ArrowUp');
    await expect(app.getByRole('tablist')).toMatchAriaSnapshot(`
      - tablist:
        - tab "Keywords"
        - tab "Competitors"
        - tab "Content outline" [selected]
    `);
    await page.keyboard.press('ArrowDown');
    await expect(app.getByRole('tablist')).toMatchAriaSnapshot(`
      - tablist:
        - tab "Keywords" [selected]
        - tab "Competitors"
        - tab "Content outline"
    `);
    await page.keyboard.press('ArrowDown');
    await expect(app.getByRole('tablist')).toMatchAriaSnapshot(`
      - tablist:
        - tab "Keywords"
        - tab "Competitors" [selected]
        - tab "Content outline"
    `);
  });

  test('Evaluate keywords', async ({ conductor }) => {
    const app = await conductor.open();
    await expect(app.getByRole('tabpanel', { name: 'Keywords' })).toBeVisible();

    await app.locator('.rank-source-selector__dropdown-indicator').click();
    await expect(app.locator('.rank-source-selector__option')).toHaveCount(223);
    await app.locator('.rank-source-selector__dropdown-indicator').click();

    await app.getByRole('textbox').fill('jawn');
    await app.getByRole('textbox').press('Enter');
    await app.getByRole('textbox').fill('tastykake');
    await app.getByRole('textbox').press('Enter');
    await app.getByRole('button', { name: 'Evaluate' }).click();
    await expect(app.locator('.keywords__rank-evaluate .conductor-button')).toBeDisabled();

    const tableContainer = app.locator('.keywords__evaluate-results table');
    await expect(tableContainer).toBeVisible();

    // Check header content.
    const headerRow = tableContainer.locator('thead tr');
    await expect(headerRow.locator('th').first()).toHaveText('Total monthly search volume');
    await expect(headerRow.locator('th').nth(1)).toHaveText('21400');

    // Check body content - first row (jawn).
    const firstBodyRow = tableContainer.locator('tbody tr').first();
    await expect(firstBodyRow.locator('td').first().locator('.tag')).toHaveText('jawn');
    await expect(firstBodyRow.locator('td').nth(1)).toHaveText('14,800');

    // Check body content - second row (tastykake).
    const secondBodyRow = tableContainer.locator('tbody tr').nth(1);
    await expect(secondBodyRow.locator('td').first().locator('.tag')).toHaveText('tastykake');
    await expect(secondBodyRow.locator('td').nth(1)).toHaveText('6,600');

    // Check footer content.
    const footerRow = tableContainer.locator('tfoot tr');
    await expect(footerRow.locator('td').first()).toHaveText('Rank 1 potential clicks per month');
    await expect(footerRow.locator('td').nth(1)).toHaveText('5798');

    await expect(app.locator('.keywords__rank-evaluate .conductor-button')).toBeDisabled();

    await app.getByRole('button', { name: 'Generate content guidance' }).click();

    await app.getByRole('tabpanel', { name: 'Competitors' }).click();
    await expect(app.getByRole('checkbox')).toHaveCount(30);
  });
});
