/**
 * Patient portal — happy path.
 *
 * Walks the seeded patient through: login → dashboard → browse doctors → open
 * doctor profile → add a family member → land back on family list. Each step
 * is a separate test so a failure tells you exactly which leg broke.
 *
 * Tests share a logged-in storage state via the {@link patientPage} helper —
 * we hit /login once at the top, then reuse cookies for every subsequent
 * test. Order matters within `test.describe.serial`.
 */
import { test, expect, type Page } from '@playwright/test';
import { PORTALS, USERS } from '../../fixtures/users';

async function login(page: Page) {
  await page.goto(`${PORTALS.patient}/login`);
  await page.getByRole('textbox', { name: 'Email' }).fill(USERS.patient.email);
  // "Password" label matches both the input AND the "Show password" toggle
  // (aria-label). Scope to the textbox role to disambiguate.
  await page.getByRole('textbox', { name: 'Password' }).fill(USERS.patient.password);
  await page.getByRole('button', { name: /sign in/i }).click();
  await page.waitForURL(/\/dashboard$/, { timeout: 15_000 });
}

test.describe.serial('Patient happy path', () => {
  test('1) login redirects to dashboard with the patient name visible', async ({ page }) => {
    await login(page);
    // Dashboard greets the user by first name. Seeded patient is "Ayesha".
    await expect(page.getByRole('heading', { level: 1 })).toContainText(/Ayesha/i);
    // The "Account" + "Up next" sections from dashboard/page.tsx are stable
    // anchors — assert they render so we know the page is fully hydrated.
    await expect(page.getByRole('heading', { name: 'Account' })).toBeVisible();
    await expect(page.getByRole('heading', { name: 'Up next' })).toBeVisible();
  });

  test('2) doctors directory lists the seeded cardiologist', async ({ page }) => {
    await login(page);
    await page.goto(`${PORTALS.patient}/doctors`);
    await expect(page.getByRole('heading', { name: /find a doctor/i })).toBeVisible();
    // Seeded doctor: Imran Rashid, cardiology. The listing renders his name as
    // the link label.
    await expect(page.getByText(/Imran Rashid/i).first()).toBeVisible({ timeout: 15_000 });
  });

  test('3) doctor profile page renders available slots block', async ({ page }) => {
    await login(page);
    await page.goto(`${PORTALS.patient}/doctors`);
    await page.getByText(/Imran Rashid/i).first().click();
    await page.waitForURL(/\/doctors\/[a-f0-9-]+$/);
    await expect(page.getByRole('heading', { name: /available slots/i })).toBeVisible({
      timeout: 15_000,
    });
  });

  test('4) family — add member flow creates a new dependent profile', async ({ page }) => {
    await login(page);
    await page.goto(`${PORTALS.patient}/family`);
    await expect(page.getByRole('heading', { name: /my family/i })).toBeVisible();

    // The "Add" button (wrapped in a <Link href="/family/new">) on the family
    // list page. Matching the button label keeps us off the heading.
    await page.getByRole('button', { name: /^add$/i }).click();
    await page.waitForURL(/\/family\/new$/);

    await page.getByLabel('First name').fill('Zayn');
    await page.getByLabel('Last name').fill('Siddiqui');
    await page.getByLabel('Date of birth').fill('2018-06-15');

    // Form button reads "Add family member" (see components/family-form.tsx).
    await page.getByRole('button', { name: /add family member/i }).click();

    // Backend returns 201 → form redirects to /family. Assert we're back and
    // the new dependent shows up in the list.
    await page.waitForURL(/\/family$/, { timeout: 15_000 });
    await expect(page.getByText(/Zayn Siddiqui/i)).toBeVisible({ timeout: 10_000 });
  });

  test('5) logout clears session and returns to login', async ({ page }) => {
    await login(page);
    await page.goto(`${PORTALS.patient}/dashboard`);
    // Header has a ghost "Sign out" / logout button — match either label.
    const logoutBtn = page.getByRole('button', { name: /sign out|log ?out/i });
    await logoutBtn.click();
    await page.waitForURL(/\/login/, { timeout: 10_000 });
  });
});
