import { type Locator, type Page } from '@playwright/test';

/**
 * Shared selectors + helpers for the e2e smoke suite. NOT a *.spec.ts, so
 * Playwright's testMatch (`**\/*.spec.ts`) never collects it as a test file.
 *
 * There are NO data-testid attributes in the frontend — these helpers pick
 * stable role/text/class hooks that already exist in the JSX. Anything that
 * required a judgement call is flagged with a `// SELECTOR-REVIEW:` comment
 * for a human to confirm against the running app.
 */

/** The click-to-edit entries grid (components/DataTable.tsx). */
export const ENTRIES_TABLE = 'table.data-table';

/**
 * Column index (0-based) of the first `<thead>` header whose text starts
 * with `label`, across the entries DataTable. The leading select-checkbox
 * column has an empty header (just a checkbox input), so it's counted and
 * body `<td>` indices line up with these header indices.
 *
 * SELECTOR-REVIEW: relies on the visible header captions ("Hours",
 * "Project", "Date", …) from EntriesPage.tsx `columns`. If a header caption
 * is renamed, update the caller's label.
 */
export async function columnIndex(page: Page, label: string): Promise<number> {
  const headers = page.locator(`${ENTRIES_TABLE} thead th`);
  const count = await headers.count();
  for (let i = 0; i < count; i++) {
    const text = (await headers.nth(i).innerText()).trim();
    if (text.startsWith(label)) return i;
  }
  throw new Error(`No entries column header starting with "${label}"`);
}

/**
 * The click-to-edit button inside `row`'s `label` column. Editable cells
 * render as `<button class="cell-edit-target" title="Click to edit">` (see
 * EntriesPage.tsx `editable()`); locked/blocked/non-editable cells render
 * plain text and this button won't exist.
 */
export async function editableCell(page: Page, row: Locator, label: string): Promise<Locator> {
  const idx = await columnIndex(page, label);
  return row.locator(':scope > td').nth(idx).locator('button.cell-edit-target');
}

/** First data row of the entries table. */
export function firstEntryRow(page: Page): Locator {
  return page.locator(`${ENTRIES_TABLE} tbody tr`).first();
}

/**
 * First REAL option in an open EntityPicker listbox — i.e. skipping the
 * "— none —" clear row (which has no `.picker-label`) and the create row
 * (`.picker-create`). EntityPicker options carry a `.picker-label` span.
 *
 * SELECTOR-REVIEW: keys off EntityPicker.tsx class names (`.picker-list`,
 * `.picker-row`, `.picker-label`). Stable as long as those persist.
 */
export function firstRealPickerOption(page: Page): Locator {
  return page
    .locator('.picker-list li.picker-row')
    .filter({ has: page.locator('.picker-label') })
    .first();
}
