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.8 Visual MathLive uses explicit Apply and Cancel without focusout commits', async ({
  page,
}) => {
  const workspaceName = `mathlive-r14-8-${Date.now()}`;
  await createBrowserWorkspace(page, { workspaceName });

  const source = page.getByLabel('LaTeX source editor');
  await source.fill([
    '\\documentclass{article}',
    '\\begin{document}',
    'Einstein wrote $E=mc^2$.',
    '\\end{document}',
    '',
  ].join('\n'));
  await source.press(saveShortcut);

  await page.getByRole('button', { name: 'Visual' }).click();
  const equation = page.getByRole('button', { name: 'Edit equation' }).first();
  await expect(equation).toBeVisible();
  await equation.click();

  let editor = page.getByTestId('mathlive-equation-editor');
  let field = editor.locator('math-field');
  await expect(field).toBeFocused();
  await setMathFieldValue(field, 'E^2=p^2c^2+m^2c^4');

  // Moving focus never commits; Cancel must leave canonical source unchanged.
  await editor.getByRole('button', { name: 'Cancel' }).click();
  await page.getByRole('button', { name: 'Source' }).click();
  await expect(source).toContainText('$E=mc^2$');
  await expect(source).not.toContainText('p^2c^2');

  await page.getByRole('button', { name: 'Visual' }).click();
  await page.getByRole('button', { name: 'Edit equation' }).first().click();
  editor = page.getByTestId('mathlive-equation-editor');
  field = editor.locator('math-field');
  await setMathFieldValue(field, 'E^2=p^2c^2+m^2c^4');
  await editor.getByRole('button', { name: 'Apply' }).click();

  await page.getByRole('button', { name: 'Source' }).click();
  await expect(source).toContainText('$E^2=p^2c^2+m^2c^4$');
});

test('R14.8 rejects a stale Visual math commit after canonical Source changes', async ({
  page,
}) => {
  const workspaceName = `math-stale-r14-8-${Date.now()}`;
  await createBrowserWorkspace(page, { workspaceName });

  const source = page.getByLabel('LaTeX source editor');
  const original = [
    '\\documentclass{article}',
    '\\begin{document}',
    'Value $a=b$.',
    '\\end{document}',
    '',
  ].join('\n');
  await source.fill(original);
  await source.press(saveShortcut);

  await page.getByRole('button', { name: 'Visual' }).click();
  await page.getByRole('button', { name: 'Edit equation' }).first().click();
  const editor = page.getByTestId('mathlive-equation-editor');
  await setMathFieldValue(editor.locator('math-field'), 'a=c');

  await page.getByRole('button', { name: 'Source' }).click();
  await source.fill(original.replace('Value ', 'Updated source '));
  await source.press(saveShortcut);
  await page.getByRole('button', { name: 'Visual' }).click();

  await editor.getByRole('button', { name: 'Apply' }).click();
  await expect(
    page.getByText(
      'The source changed while the equation editor was open. Reopen the equation and try again.',
    ),
  ).toBeVisible();

  await page.getByRole('button', { name: 'Source' }).click();
  await expect(source).toContainText('Updated source $a=b$.');
  await expect(source).not.toContainText('$a=c$');
});

test('R14.8 keeps structural equations source-only in Visual mode', async ({
  page,
}) => {
  const workspaceName = `math-protected-r14-8-${Date.now()}`;
  await createBrowserWorkspace(page, { workspaceName });

  const source = page.getByLabel('LaTeX source editor');
  await source.fill([
    '\\documentclass{article}',
    '\\begin{document}',
    'Protected $E=mc^2\\label{eq:energy}$ equation.',
    '\\end{document}',
    '',
  ].join('\n'));
  await source.press(saveShortcut);

  await page.getByRole('button', { name: 'Visual' }).click();
  const protectedEquation = page.getByRole('button', {
    name: 'Source-only equation',
  });
  await expect(protectedEquation).toBeVisible();
  await protectedEquation.click();
  await expect(page.getByTestId('mathlive-equation-editor')).toHaveCount(0);
  await expect(
    page.getByText(
      'This equation contains structural LaTeX directives that Learnitive will not send through MathLive.',
    ),
  ).toBeVisible();
});
