import { expect, test, type Locator } from '@playwright/test';
import { createBrowserWorkspace } from './common';

const saveShortcut = process.platform === 'darwin' ? 'Meta+s' : 'Control+s';

async function setMathFieldValue(field: Locator, value: string) {
  await field.evaluate((element, nextValue) => {
    const math = element as HTMLElement & { value: string };
    math.value = nextValue;
    math.dispatchEvent(new Event('input', { bubbles: true }));
  }, value);
}

test('R14.18 Source and Visual share the Learnitive MathLive exact-source model', async ({ page }) => {
  const workspaceName = `math-r14-18-${Date.now()}`;
  const pageErrors: string[] = [];
  page.on('pageerror', (error) => pageErrors.push(error.message));
  await createBrowserWorkspace(page, { workspaceName });

  const source = page.getByLabel('LaTeX source editor');
  await source.fill([
    '\\documentclass{article}',
    '\\begin{document}',
    'Math value $x$.',
    'Visual target.',
    '\\end{document}',
    '',
  ].join('\n'));
  await source.press(saveShortcut);

  // Cursor-driven Learnitive Source preview resolves the shared canonical region.
  const mathLine = page.locator('[data-latex-codemirror] .cm-line').filter({ hasText: 'Math value $x$.' });
  await mathLine.click();
  await source.press('Home');
  for (let index = 0; index < 'Math value $'.length; index += 1) await source.press('ArrowRight');
  const sourcePreview = page.getByTestId('interactive-mathlive-preview');
  await expect(sourcePreview).toBeVisible();
  await sourcePreview.getByRole('button', { name: 'Edit' }).click();

  let editor = page.getByTestId('mathlive-equation-editor');
  await expect(editor).toBeVisible();
  await editor.getByRole('button', { name: 'Symbols' }).click();
  await editor.getByLabel('Search equation symbols').fill('gamma');
  await expect(editor.getByTitle(/\\gamma/).first()).toBeVisible();
  await setMathFieldValue(editor.locator('math-field'), 'y');
  await editor.getByRole('button', { name: 'Apply' }).click();
  await expect(source).toContainText('Math value $y$.');

  // The Visual equation adapter opens the same React MathLive editor and
  // commits through LatexDocumentController.applyExactEdit.
  await page.getByRole('button', { name: 'Visual' }).click();
  const visual = page.locator('.interactive-latex-visual-editor');
  await expect(visual).toBeVisible();
  await page.getByRole('button', { name: 'Edit equation' }).first().click();
  editor = page.getByTestId('mathlive-equation-editor');
  await setMathFieldValue(editor.locator('math-field'), 'z');
  await editor.getByRole('button', { name: 'Apply' }).click();

  await page.getByRole('button', { name: 'Source' }).click();
  await expect(source).toContainText('Math value $z$.');
  expect(pageErrors.filter((message) => /MathLive|Mathfield|ErrorBoundary/i.test(message))).toEqual([]);
});

test('R14.18 typed slash stays editable and Source ↔ Visual remains canonical through 100 switches', async ({ page }) => {
  const workspaceName = `visual-session-r14-18-${Date.now()}`;
  await createBrowserWorkspace(page, { workspaceName });
  const source = page.getByLabel('LaTeX source editor');
  await source.fill([
    '\\documentclass{article}',
    '\\begin{document}',
    'R14.18 editable paragraph.',
    '\\end{document}',
    '',
  ].join('\n'));
  await source.press(saveShortcut);

  await page.getByRole('button', { name: 'Visual' }).click();
  const visual = page.locator('.interactive-latex-visual-editor');
  const paragraph = visual.locator('.interactive-visual-paragraph').filter({ hasText: 'R14.18 editable paragraph.' });
  await expect(paragraph).toBeVisible();
  await paragraph.fill('R14.18 Visual canonical edit.');
  await paragraph.click();
  await paragraph.press('/');
  await page.keyboard.type('inline');
  const slash = page.getByTestId('latex-visual-slash-menu');
  await expect(slash).toBeVisible();
  await expect(slash.getByText('Inline Math', { exact: true })).toBeVisible();
  await page.keyboard.press('Escape');

  for (let index = 0; index < 100; index += 1) {
    await page.getByRole('button', { name: 'Source' }).click();
    await expect(source).toContainText('R14.18 Visual canonical edit.');
    await page.getByRole('button', { name: 'Visual' }).click();
    await expect(visual).toContainText('R14.18 Visual canonical edit.');
  }

  await page.getByRole('button', { name: 'Source' }).click();
  await source.fill([
    '\\documentclass{article}',
    '\\begin{document}',
    'R14.18 Source canonical edit.',
    '\\end{document}',
    '',
  ].join('\n'));
  await page.getByRole('button', { name: 'Visual' }).click();
  await expect(visual).toContainText('R14.18 Source canonical edit.');
});
