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

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

async function createTextFile(
  page: import('@playwright/test').Page,
  fileName: string,
  content: string,
) {
  const explorer = page.getByTestId('interactive-file-explorer');
  await explorer.getByRole('button', { name: 'New File' }).click();
  const dialog = page.getByRole('dialog', { name: 'Create Project File' });
  await dialog.getByLabel('File name').fill(fileName);
  await dialog.getByRole('button', { name: 'Create' }).click();
  const source = page.getByLabel('LaTeX source editor');
  await expect(source).toBeVisible();
  await source.fill(content);
  await source.press(saveShortcut);
  await expect(page.getByText('Saved', { exact: true })).toBeVisible();
}

test('R14.17 atomically switches 100 source-file sessions without showing stale content', async ({ page }) => {
  const workspaceName = `session-r14-17-${Date.now()}`;
  await createBrowserWorkspace(page, { workspaceName });

  const source = page.getByLabel('LaTeX source editor');
  await expect(source).toBeVisible();
  await source.fill('MAIN-CONTENT\n');
  await source.press(saveShortcut);

  await createTextFile(page, 'chapter.tex', 'CHAPTER-CONTENT\n');
  await createTextFile(page, 'style.sty', '% STYLE-CONTENT\n');
  await createTextFile(page, 'refs.bib', '@misc{r1417,title={BIB-CONTENT}}\n');

  const targets = [
    { name: /^main\.tex$/, marker: 'MAIN-CONTENT' },
    { name: /^chapter\.tex$/, marker: 'CHAPTER-CONTENT' },
    { name: /^style\.sty$/, marker: 'STYLE-CONTENT' },
    { name: /^refs\.bib$/, marker: 'BIB-CONTENT' },
  ] as const;

  for (let index = 0; index < 100; index += 1) {
    const target = targets[index % targets.length]!;
    await page.getByRole('link', { name: target.name }).click();
    const activeSource = page.getByLabel('LaTeX source editor');
    await expect(activeSource).toBeVisible();
    await expect(activeSource).toContainText(target.marker);
    for (const other of targets) {
      if (other === target) continue;
      await expect(activeSource).not.toContainText(other.marker);
    }
  }
});

test('R14.17 restores per-file CodeMirror selection, scroll and undo history', async ({ page }) => {
  const workspaceName = `state-r14-17-${Date.now()}`;
  await createBrowserWorkspace(page, { workspaceName });

  const source = page.getByLabel('LaTeX source editor');
  const mainText = [
    '\\documentclass{article}',
    '\\begin{document}',
    ...Array.from({ length: 620 }, (_, index) => `Main line ${index + 1}`),
    'MAIN-HISTORY-BASE',
    '\\end{document}',
    '',
  ].join('\n');
  await source.fill(mainText);
  await source.press(saveShortcut);
  await source.press(process.platform === 'darwin' ? 'Meta+ArrowDown' : 'Control+End');
  await page.keyboard.type('MAIN-HISTORY-EDIT');

  const mainCursorLine = Number(
    (await page.getByTestId('latex-cursor-location').textContent())?.match(/Ln\s+(\d+)/)?.[1] ?? 0,
  );
  expect(mainCursorLine).toBeGreaterThan(600);

  const mainScroller = page.locator('[data-latex-codemirror] .cm-scroller');
  await mainScroller.evaluate((element) => {
    element.scrollTop = element.scrollHeight;
    element.dispatchEvent(new Event('scroll'));
  });
  const savedScrollTop = await mainScroller.evaluate((element) => element.scrollTop);
  expect(savedScrollTop).toBeGreaterThan(500);

  await createTextFile(page, 'chapter.tex', 'CHAPTER-STATE-CONTENT\n');
  await page.getByRole('link', { name: /^main\.tex$/ }).click();

  const restoredSource = page.getByLabel('LaTeX source editor');
  await expect(restoredSource).toContainText('MAIN-HISTORY-EDIT');
  await expect(page.getByTestId('latex-cursor-location')).toContainText(`Ln ${mainCursorLine}`);
  const restoredScrollTop = await page
    .locator('[data-latex-codemirror] .cm-scroller')
    .evaluate((element) => element.scrollTop);
  expect(restoredScrollTop).toBeGreaterThan(500);

  await restoredSource.press(undoShortcut);
  await expect(restoredSource).not.toContainText('MAIN-HISTORY-EDIT');
  await expect(restoredSource).toContainText('MAIN-HISTORY-BASE');
});
