import { test, expect } from '@playwright/test';

/**
 * ============================================
 * LESSON 5: REAL SCENARIOS
 * ============================================
 *
 * You now know the core trio:
 *   1. LOCATORS   → FIND the element     (Lesson 1)
 *   2. ACTIONS    → DO something to it   (Lesson 2)
 *   3. ASSERTIONS → VERIFY the result    (Lesson 3)
 *   + NAVIGATION & WAITS                 (Lesson 4)
 *
 * This lesson puts it all together on the messy, real-world stuff you
 * hit in EVERY app:
 *   - Login / logout flows
 *   - Forms (text, radio, checkbox, textarea, submit)
 *   - Dropdowns (native <select>)
 *   - Alerts & dialogs (the browser popups: alert / confirm / prompt)
 *   - New tabs / windows (popups that open a second page)
 *   - File upload
 *
 * As a manual tester you handle these by instinct. Here you'll learn the
 * Playwright command for each. These are the patterns interviewers ask
 * about, so this lesson is worth doing carefully.
 *
 * NOTE ON TEST SITES:
 *   We use public practice sites (the-internet.herokuapp.com and
 *   demoqa-style patterns). If a site is down, the CONCEPT still stands —
 *   the commands are identical against your real app.
 */

test.describe('Lesson 5: Real Scenarios', () => {

  // ─────────────────────────────────────────────
  // 5.1 - LOGIN FLOW (fill + click + verify)
  // ─────────────────────────────────────────────
  test('5.1 - login: valid credentials', async ({ page }) => {
    await page.goto('https://the-internet.herokuapp.com/login');

    // Fill the form fields (these are the known valid creds for this site)
    await page.getByLabel('Username').fill('tomsmith');
    await page.getByLabel('Password').fill('SuperSecretPassword!');

    // Submit by clicking the login button
    await page.getByRole('button', { name: 'Login' }).click();

    // Verify we're logged in: a success flash message appears
    await expect(page.locator('#flash')).toContainText('You logged into a secure area!');

    // And a Logout button is now visible
    await expect(page.getByRole('link', { name: 'Logout' })).toBeVisible();
  });

  // ─────────────────────────────────────────────
  // 5.2 - LOGIN FLOW (invalid credentials — negative test)
  // ─────────────────────────────────────────────
  test('5.2 - login: invalid credentials show an error', async ({ page }) => {
    await page.goto('https://the-internet.herokuapp.com/login');

    await page.getByLabel('Username').fill('wronguser');
    await page.getByLabel('Password').fill('wrongpass');
    await page.getByRole('button', { name: 'Login' }).click();

    // Negative tests are just as important as positive ones!
    await expect(page.locator('#flash')).toContainText('Your username is invalid!');
  });

  // ─────────────────────────────────────────────
  // 5.3 - LOGOUT (complete the round trip)
  // ─────────────────────────────────────────────
  test('5.3 - logout: return to login page', async ({ page }) => {
    // Log in first
    await page.goto('https://the-internet.herokuapp.com/login');
    await page.getByLabel('Username').fill('tomsmith');
    await page.getByLabel('Password').fill('SuperSecretPassword!');
    await page.getByRole('button', { name: 'Login' }).click();

    // Now log out
    await page.getByRole('link', { name: 'Logout' }).click();

    // Verify we're back and see the logout confirmation
    await expect(page.locator('#flash')).toContainText('You logged out of the secure area!');
  });

  // ─────────────────────────────────────────────
  // 5.4 - CHECKBOXES (check / uncheck / verify state)
  // ─────────────────────────────────────────────
  test('5.4 - checkboxes: tick and untick', async ({ page }) => {
    await page.goto('https://the-internet.herokuapp.com/checkboxes');

    const checkboxes = page.locator('input[type="checkbox"]');
    const first = checkboxes.nth(0);   // nth(0) = first, nth(1) = second
    const second = checkboxes.nth(1);

    // check() guarantees it ends up TICKED (no matter its starting state)
    await first.check();
    await expect(first).toBeChecked();

    // uncheck() guarantees it ends up UNTICKED
    await second.uncheck();
    await expect(second).not.toBeChecked();
  });

  // ─────────────────────────────────────────────
  // 5.5 - DROPDOWN (native <select> — selectOption)
  // ─────────────────────────────────────────────
  test('5.5 - dropdown: select an option', async ({ page }) => {
    await page.goto('https://the-internet.herokuapp.com/dropdown');

    const dropdown = page.locator('#dropdown');

    // selectOption can pick by VALUE, LABEL, or INDEX:
    await dropdown.selectOption('1');                 // by value attribute
    await expect(dropdown).toHaveValue('1');

    await dropdown.selectOption({ label: 'Option 2' }); // by visible text
    await expect(dropdown).toHaveValue('2');

    /**
     * selectOption only works on NATIVE <select> elements.
     * Custom dropdowns (built with divs, like React/Angular components)
     * are just click + click:
     *   await page.click('.dropdown-toggle');
     *   await page.getByText('Option 2').click();
     */
  });

  // ─────────────────────────────────────────────
  // 5.6 - JS ALERT (dialog handler — accept)
  // ─────────────────────────────────────────────
  test('5.6 - alert: accept a JS alert', async ({ page }) => {
    await page.goto('https://the-internet.herokuapp.com/javascript_alerts');

    /**
     * ★ KEY IDEA: You must register the dialog handler BEFORE the click
     * that triggers it. Playwright can't "see" a popup after the fact —
     * you tell it in advance what to do when a dialog appears.
     */
    page.on('dialog', async (dialog) => {
      console.log(`Dialog type: ${dialog.type()}`);    // "alert"
      console.log(`Dialog message: ${dialog.message()}`);
      await dialog.accept();   // click OK
    });

    // Now trigger the alert
    await page.getByRole('button', { name: 'Click for JS Alert' }).click();

    // The page reports the result
    await expect(page.locator('#result')).toHaveText('You successfully clicked an alert');
  });

  // ─────────────────────────────────────────────
  // 5.7 - JS CONFIRM (dialog handler — dismiss/cancel)
  // ─────────────────────────────────────────────
  test('5.7 - confirm: dismiss a JS confirm dialog', async ({ page }) => {
    await page.goto('https://the-internet.herokuapp.com/javascript_alerts');

    // This time we DISMISS (click Cancel) instead of accept
    page.once('dialog', async (dialog) => {
      await dialog.dismiss();   // click Cancel
    });

    await page.getByRole('button', { name: 'Click for JS Confirm' }).click();

    await expect(page.locator('#result')).toHaveText('You clicked: Cancel');

    /**
     * page.on   = handle EVERY dialog (stays registered)
     * page.once = handle just the NEXT dialog (auto-removes itself)
     */
  });

  // ─────────────────────────────────────────────
  // 5.8 - JS PROMPT (dialog handler — type text then accept)
  // ─────────────────────────────────────────────
  test('5.8 - prompt: type into a JS prompt', async ({ page }) => {
    await page.goto('https://the-internet.herokuapp.com/javascript_alerts');

    page.once('dialog', async (dialog) => {
      // accept() can take the text to type into the prompt box
      await dialog.accept('Shikha automated this!');
    });

    await page.getByRole('button', { name: 'Click for JS Prompt' }).click();

    await expect(page.locator('#result')).toHaveText('You entered: Shikha automated this!');
  });

  // ─────────────────────────────────────────────
  // 5.9 - NEW TAB / WINDOW (handle a popup page)
  // ─────────────────────────────────────────────
  test('5.9 - new tab: capture a popup window', async ({ page, context }) => {
    await page.goto('https://the-internet.herokuapp.com/windows');

    /**
     * ★ KEY IDEA: When a click opens a NEW tab, you must catch it.
     * Set up the waiter BEFORE the click, then await both together.
     */
    const pagePromise = context.waitForEvent('page');   // wait for a new page
    await page.getByRole('link', { name: 'Click Here' }).click();
    const newPage = await pagePromise;                  // this is the new tab

    // Wait for the new tab to finish loading, then act on IT (not "page")
    await newPage.waitForLoadState();
    await expect(newPage.locator('h3')).toHaveText('New Window');

    // You can close the popup and continue on the original tab
    await newPage.close();
    await expect(page.getByRole('link', { name: 'Click Here' })).toBeVisible();
  });

  // ─────────────────────────────────────────────
  // 5.10 - FILE UPLOAD (setInputFiles)
  // ─────────────────────────────────────────────
  test('5.10 - file upload: attach a file', async ({ page }) => {
    await page.goto('https://the-internet.herokuapp.com/upload');

    /**
     * For a standard <input type="file">, you do NOT click and browse.
     * You set the file path directly with setInputFiles(). Much more reliable.
     * We upload THIS very test file as the sample.
     */
    const filePath = __filename;   // path to this .spec.ts file itself
    await page.locator('#file-upload').setInputFiles(filePath);

    await page.getByRole('button', { name: 'Upload' }).click();

    // The site echoes back the uploaded file name
    await expect(page.locator('#uploaded-files')).toContainText('lesson05-real-scenarios.spec.ts');
  });


  /**
   * ═══════════════════════════════════════════════
   * YOUR EXERCISES
   * ═══════════════════════════════════════════════
   *
   * Remove the // comments to activate each test, then fill in the blanks.
   * Run one at a time with:
   *   npx playwright test lesson05-real-scenarios --headed
   */

  // Exercise 5.11: Full login round-trip in ONE test.
  //   1. Log in with tomsmith / SuperSecretPassword!
  //   2. Assert the success flash message
  //   3. Click Logout
  //   4. Assert the logout flash message
  //
  // test('5.11 - EXERCISE: login then logout', async ({ page }) => {
  //   await page.goto('https://the-internet.herokuapp.com/login');
  //   // your code...
  // });


  // Exercise 5.12: Dropdown selection.
  //   Go to /dropdown, select "Option 1" by label,
  //   then assert the dropdown value is "1".
  //
  // test('5.12 - EXERCISE: pick a dropdown option', async ({ page }) => {
  //   await page.goto('https://the-internet.herokuapp.com/dropdown');
  //   // Hint: page.locator('#dropdown').selectOption({ label: 'Option 1' })
  // });


  // Exercise 5.13: Handle a JS confirm by ACCEPTING it this time.
  //   Register a page.once('dialog') handler that calls dialog.accept(),
  //   click "Click for JS Confirm", then assert #result shows
  //   "You clicked: Ok".
  //
  // test('5.13 - EXERCISE: accept a confirm', async ({ page }) => {
  //   await page.goto('https://the-internet.herokuapp.com/javascript_alerts');
  //   // your code...
  // });


  // Exercise 5.14: New tab.
  //   Go to /windows, open the popup, and assert the new tab's URL
  //   contains "windows/new".
  //   Hint: use context.waitForEvent('page') BEFORE the click,
  //         then expect(newPage).toHaveURL(/windows\/new/)
  //
  // test('5.14 - EXERCISE: verify new tab URL', async ({ page, context }) => {
  //   await page.goto('https://the-internet.herokuapp.com/windows');
  //   // your code...
  // });

});
