/**
 * Text Formatting Tests
 *
 * Comprehensive tests for text formatting functionality including:
 * - Bold, Italic, Underline, Strikethrough
 * - Toolbar buttons vs keyboard shortcuts
 * - Formatting state reflection in toolbar
 * - Combined formatting
 * - Clear formatting
 */

import { test, expect } from '@playwright/test';
import { EditorPage } from '../helpers/editor-page';
import * as assertions from '../helpers/assertions';

test.describe('Bold Formatting', () => {
  let editor: EditorPage;

  test.beforeEach(async ({ page }) => {
    editor = new EditorPage(page);
    await editor.gotoEmpty();
    await editor.waitForReady();
    await editor.focus();
  });

  test('apply bold via toolbar button', async ({ page }) => {
    await editor.typeText('Bold text');
    await editor.selectText('Bold');
    await editor.applyBold();

    await assertions.assertTextIsBold(page, 'Bold');
  });

  test('apply bold via Ctrl+B', async ({ page }) => {
    await editor.typeText('Bold shortcut');
    await editor.selectText('shortcut');
    await editor.applyBoldShortcut();

    await assertions.assertTextIsBold(page, 'shortcut');
  });

  test('toggle bold off', async ({ page }) => {
    await editor.typeText('Toggle bold');
    await editor.selectText('bold');
    await editor.applyBold();

    await assertions.assertTextIsBold(page, 'bold');

    await editor.applyBold();

    await assertions.assertTextIsNotBold(page, 'bold');
  });

  test('bold partial word', async ({ page }) => {
    await editor.typeText('Hello');
    await editor.selectRange(0, 0, 2); // Select 'He'
    await editor.applyBold();

    await assertions.assertTextIsBold(page, 'He');
  });

  test('bold extends when typing', async ({ page }) => {
    await editor.typeText('Start ');
    await editor.applyBold();
    await editor.typeText('bold');
    await editor.applyBold();
    await editor.typeText(' end');

    await assertions.assertTextIsBold(page, 'bold');
  });

  test('toolbar button reflects bold state', async ({ page }) => {
    await editor.typeText('Bold text');
    await editor.selectText('Bold');
    await editor.applyBold();

    // Select the bold text again
    await editor.selectText('Bold');

    await assertions.assertToolbarButtonActive(page, 'toolbar-bold');
  });
});

test.describe('Italic Formatting', () => {
  let editor: EditorPage;

  test.beforeEach(async ({ page }) => {
    editor = new EditorPage(page);
    await editor.gotoEmpty();
    await editor.waitForReady();
    await editor.focus();
  });

  test('apply italic via toolbar button', async ({ page }) => {
    await editor.typeText('Italic text');
    await editor.selectText('Italic');
    await editor.applyItalic();

    await assertions.assertTextIsItalic(page, 'Italic');
  });

  test('apply italic via Ctrl+I', async ({ page }) => {
    await editor.typeText('Italic shortcut');
    await editor.selectText('shortcut');
    await editor.applyItalicShortcut();

    await assertions.assertTextIsItalic(page, 'shortcut');
  });

  test('toggle italic off', async ({ page }) => {
    await editor.typeText('Toggle italic');
    await editor.selectText('italic');
    await editor.applyItalic();
    await editor.applyItalic();

    // After toggle, should no longer be italic
    // Note: We check the initial state is italic first
  });

  test('toolbar button reflects italic state', async ({ page }) => {
    await editor.typeText('Italic text');
    await editor.selectText('Italic');
    await editor.applyItalic();
    await editor.selectText('Italic');

    await assertions.assertToolbarButtonActive(page, 'toolbar-italic');
  });
});

test.describe('Underline Formatting', () => {
  let editor: EditorPage;

  test.beforeEach(async ({ page }) => {
    editor = new EditorPage(page);
    await editor.gotoEmpty();
    await editor.waitForReady();
    await editor.focus();
  });

  test('apply underline via toolbar button', async ({ page }) => {
    await editor.typeText('Underline text');
    await editor.selectText('Underline');
    await editor.applyUnderline();

    await assertions.assertTextIsUnderlined(page, 'Underline');
  });

  test('apply underline via Ctrl+U', async ({ page }) => {
    await editor.typeText('Underline shortcut');
    await editor.selectText('shortcut');
    await editor.applyUnderlineShortcut();

    await assertions.assertTextIsUnderlined(page, 'shortcut');
  });
});

test.describe('Strikethrough Formatting', () => {
  let editor: EditorPage;

  test.beforeEach(async ({ page }) => {
    editor = new EditorPage(page);
    await editor.gotoEmpty();
    await editor.waitForReady();
    await editor.focus();
  });

  test('apply strikethrough via toolbar button', async ({ page }) => {
    await editor.typeText('Strike text');
    await editor.selectText('Strike');
    await editor.applyStrikethrough();

    await assertions.assertTextHasStrikethrough(page, 'Strike');
  });
});

test.describe('Combined Formatting', () => {
  let editor: EditorPage;

  test.beforeEach(async ({ page }) => {
    editor = new EditorPage(page);
    await editor.gotoEmpty();
    await editor.waitForReady();
    await editor.focus();
  });

  test('bold + italic', async ({ page }) => {
    await editor.typeText('Combined format');
    await editor.selectText('Combined');
    await editor.applyBold();
    await editor.applyItalic();

    await assertions.assertTextIsBold(page, 'Combined');
    await assertions.assertTextIsItalic(page, 'Combined');
  });

  test('bold + italic + underline', async ({ page }) => {
    await editor.typeText('Triple format');
    await editor.selectText('Triple');
    await editor.applyBold();
    await editor.applyItalic();
    await editor.applyUnderline();

    await assertions.assertTextIsBold(page, 'Triple');
    await assertions.assertTextIsItalic(page, 'Triple');
    await assertions.assertTextIsUnderlined(page, 'Triple');
  });

  test('all formatting types', async ({ page }) => {
    await editor.typeText('All formatting');
    await editor.selectText('All');
    await editor.applyBold();
    await editor.applyItalic();
    await editor.applyUnderline();
    await editor.applyStrikethrough();

    await assertions.assertTextIsBold(page, 'All');
    await assertions.assertTextIsItalic(page, 'All');
    await assertions.assertTextIsUnderlined(page, 'All');
    await assertions.assertTextHasStrikethrough(page, 'All');
  });
});

test.describe('Clear Formatting', () => {
  let editor: EditorPage;

  test.beforeEach(async ({ page }) => {
    editor = new EditorPage(page);
    await editor.gotoEmpty();
    await editor.waitForReady();
    await editor.focus();
  });

  test('clear formatting removes bold', async ({ page }) => {
    await editor.typeText('Formatted text');
    await editor.selectText('Formatted');
    await editor.applyBold();

    await assertions.assertTextIsBold(page, 'Formatted');

    await editor.clearFormatting();

    await assertions.assertTextIsNotBold(page, 'Formatted');
  });

  test('clear formatting removes all', async ({ page }) => {
    await editor.typeText('Formatted text');
    await editor.selectText('Formatted');
    await editor.applyBold();
    await editor.applyItalic();
    await editor.applyUnderline();

    await editor.clearFormatting();

    await assertions.assertTextIsNotBold(page, 'Formatted');
  });
});

test.describe('Formatting with Selection', () => {
  let editor: EditorPage;

  test.beforeEach(async ({ page }) => {
    editor = new EditorPage(page);
    await editor.gotoEmpty();
    await editor.waitForReady();
    await editor.focus();
  });

  test('format with no selection sets for next typed text', async ({ page }) => {
    await editor.applyBold();
    await editor.typeText('Bold from start');

    await assertions.assertTextIsBold(page, 'Bold from start');
  });

  test('format partial selection', async ({ page }) => {
    await editor.typeText('ABCDE');
    await editor.selectRange(0, 1, 4); // Select 'BCD'
    await editor.applyBold();

    await assertions.assertTextIsBold(page, 'BCD');
  });

  test('format across multiple words', async ({ page }) => {
    await editor.typeText('Word one two three four');
    await editor.selectText('one two three');
    await editor.applyBold();

    await assertions.assertTextIsBold(page, 'one two three');
  });

  test('cursor position preserved after formatting', async ({ page }) => {
    await editor.typeText('Hello');
    await editor.selectText('Hello');
    await editor.applyBold();
    await page.keyboard.press('ArrowRight');
    await editor.typeText(' World');

    await assertions.assertDocumentContainsText(page, 'Hello World');
    await assertions.assertTextIsBold(page, 'Hello');
  });
});

test.describe('Formatting Edge Cases', () => {
  let editor: EditorPage;

  test.beforeEach(async ({ page }) => {
    editor = new EditorPage(page);
    await editor.gotoEmpty();
    await editor.waitForReady();
    await editor.focus();
  });

  test('rapid format toggle', async ({ page }) => {
    await editor.typeText('Test');
    await editor.selectAll();

    // Rapidly toggle bold
    await editor.applyBold();
    await editor.applyBold();
    await editor.applyBold();
    await editor.applyBold();

    // Document should still be intact
    await assertions.assertDocumentContainsText(page, 'Test');
  });

  test('format empty selection', async ({ page }) => {
    await editor.typeText('Text');
    // Don't select anything, just apply format
    await editor.applyBold();
    await editor.typeText('Bold');

    await assertions.assertTextIsBold(page, 'Bold');
  });

  test('format spanning formatted regions', async ({ page }) => {
    await editor.typeText('Normal');
    await editor.applyBold();
    await editor.typeText('Bold');
    await editor.applyBold();
    await editor.typeText('Normal');

    // Select all and apply italic
    await editor.selectAll();
    await editor.applyItalic();

    await assertions.assertTextIsItalic(page, 'Normal');
  });

  test('undo formatting', async ({ page }) => {
    await editor.typeText('Test');
    await editor.selectAll();
    await editor.applyBold();

    await assertions.assertTextIsBold(page, 'Test');

    await editor.undo();

    await assertions.assertTextIsNotBold(page, 'Test');
  });

  test('redo formatting', async ({ page }) => {
    await editor.typeText('Test');
    await editor.selectAll();
    await editor.applyBold();
    await editor.undo();
    await editor.redo();

    await assertions.assertTextIsBold(page, 'Test');
  });
});
