import { expect, tap, webhelpers } from '@git.zone/tstest/tapbundle';
import { DeesInputWysiwyg } from '../ts_web/elements/00group-input/dees-input-wysiwyg/dees-input-wysiwyg.js';
import { DeesWysiwygBlock } from '../ts_web/elements/00group-input/dees-input-wysiwyg/dees-wysiwyg-block.js';

tap.test('Keyboard: Arrow navigation between blocks', async () => {
  const editor: DeesInputWysiwyg = await webhelpers.fixture(
    webhelpers.html`<dees-input-wysiwyg></dees-input-wysiwyg>`
  );
  
  // Import multiple blocks
  editor.importBlocks([
    { id: 'block-1', type: 'paragraph', content: 'First paragraph' },
    { id: 'block-2', type: 'paragraph', content: 'Second paragraph' },
    { id: 'block-3', type: 'paragraph', content: 'Third paragraph' }
  ]);
  
  await editor.updateComplete;
  await new Promise(resolve => setTimeout(resolve, 100));
  
  // Focus first block at end
  const firstBlockWrapper = editor.shadowRoot?.querySelector('[data-block-id="block-1"]');
  const firstBlockComponent = firstBlockWrapper?.querySelector('dees-wysiwyg-block') as DeesWysiwygBlock;
  const firstBlockContainer = firstBlockComponent?.shadowRoot?.querySelector('.wysiwyg-block-container') as HTMLElement;
  const firstParagraph = firstBlockContainer?.querySelector('.block.paragraph') as HTMLElement;
  
  // Focus and set cursor at end of first block
  firstParagraph.focus();
  const textNode = firstParagraph.firstChild;
  if (textNode && textNode.nodeType === Node.TEXT_NODE) {
    const range = document.createRange();
    const selection = window.getSelection();
    range.setStart(textNode, textNode.textContent?.length || 0);
    range.setEnd(textNode, textNode.textContent?.length || 0);
    selection?.removeAllRanges();
    selection?.addRange(range);
  }
  
  await new Promise(resolve => setTimeout(resolve, 100));
  
  // Press ArrowRight to move to second block
  const arrowRightEvent = new KeyboardEvent('keydown', {
    key: 'ArrowRight',
    code: 'ArrowRight',
    bubbles: true,
    cancelable: true,
    composed: true
  });
  
  firstParagraph.dispatchEvent(arrowRightEvent);
  await new Promise(resolve => setTimeout(resolve, 200));
  
  // Check if second block is focused
  const secondBlockWrapper = editor.shadowRoot?.querySelector('[data-block-id="block-2"]');
  const secondBlockComponent = secondBlockWrapper?.querySelector('dees-wysiwyg-block') as DeesWysiwygBlock;
  const secondBlockContainer = secondBlockComponent?.shadowRoot?.querySelector('.wysiwyg-block-container') as HTMLElement;
  const secondParagraph = secondBlockContainer?.querySelector('.block.paragraph') as HTMLElement;
  
  // Check if the second paragraph has focus
  const activeElement = secondBlockComponent.shadowRoot?.activeElement;
  expect(activeElement).toEqual(secondParagraph);
  
  console.log('Arrow navigation test complete');
});

tap.test('Keyboard: Backspace merges blocks', async () => {
  const editor: DeesInputWysiwyg = await webhelpers.fixture(
    webhelpers.html`<dees-input-wysiwyg></dees-input-wysiwyg>`
  );
  
  // Import two blocks
  editor.importBlocks([
    { id: 'merge-1', type: 'paragraph', content: 'First' },
    { id: 'merge-2', type: 'paragraph', content: 'Second' }
  ]);
  
  await editor.updateComplete;
  await new Promise(resolve => setTimeout(resolve, 100));
  
  // Focus second block at beginning
  const secondBlockWrapper = editor.shadowRoot?.querySelector('[data-block-id="merge-2"]');
  const secondBlockComponent = secondBlockWrapper?.querySelector('dees-wysiwyg-block') as DeesWysiwygBlock;
  const secondBlockContainer = secondBlockComponent?.shadowRoot?.querySelector('.wysiwyg-block-container') as HTMLElement;
  const secondParagraph = secondBlockContainer?.querySelector('.block.paragraph') as HTMLElement;
  
  // Focus and set cursor at beginning
  secondParagraph.focus();
  const textNode = secondParagraph.firstChild;
  if (textNode && textNode.nodeType === Node.TEXT_NODE) {
    const range = document.createRange();
    const selection = window.getSelection();
    range.setStart(textNode, 0);
    range.setEnd(textNode, 0);
    selection?.removeAllRanges();
    selection?.addRange(range);
  }
  
  await new Promise(resolve => setTimeout(resolve, 100));
  
  // Press Backspace to merge with previous block
  const backspaceEvent = new KeyboardEvent('keydown', {
    key: 'Backspace',
    code: 'Backspace',
    bubbles: true,
    cancelable: true,
    composed: true
  });
  
  secondParagraph.dispatchEvent(backspaceEvent);
  await new Promise(resolve => setTimeout(resolve, 200));
  
  // Check if blocks were merged
  expect(editor.blocks.length).toEqual(1);
  expect(editor.blocks[0].content).toContain('First');
  expect(editor.blocks[0].content).toContain('Second');
  
  console.log('Backspace merge test complete');
});

tap.test('Keyboard: Delete key on non-editable blocks', async () => {
  const editor: DeesInputWysiwyg = await webhelpers.fixture(
    webhelpers.html`<dees-input-wysiwyg></dees-input-wysiwyg>`
  );
  
  // Import blocks including a divider
  editor.importBlocks([
    { id: 'para-1', type: 'paragraph', content: 'Before divider' },
    { id: 'div-1', type: 'divider', content: '' },
    { id: 'para-2', type: 'paragraph', content: 'After divider' }
  ]);
  
  await editor.updateComplete;
  await new Promise(resolve => setTimeout(resolve, 100));
  
  // Focus the divider block
  const dividerBlockWrapper = editor.shadowRoot?.querySelector('[data-block-id="div-1"]');
  const dividerBlockComponent = dividerBlockWrapper?.querySelector('dees-wysiwyg-block') as DeesWysiwygBlock;
  const dividerBlockContainer = dividerBlockComponent?.shadowRoot?.querySelector('.wysiwyg-block-container') as HTMLElement;
  const dividerElement = dividerBlockContainer?.querySelector('.block.divider') as HTMLElement;
  
  // Non-editable blocks need to be focused differently
  dividerElement?.focus();
  await new Promise(resolve => setTimeout(resolve, 100));
  
  // Press Delete to remove the divider
  const deleteEvent = new KeyboardEvent('keydown', {
    key: 'Delete',
    code: 'Delete',
    bubbles: true,
    cancelable: true,
    composed: true
  });
  
  dividerElement.dispatchEvent(deleteEvent);
  await new Promise(resolve => setTimeout(resolve, 200));
  
  // Check if divider was removed
  expect(editor.blocks.length).toEqual(2);
  expect(editor.blocks.find(b => b.type === 'divider')).toBeUndefined();
  
  console.log('Delete key on non-editable block test complete');
});

tap.test('Keyboard: Tab key in code block', async () => {
  const editor: DeesInputWysiwyg = await webhelpers.fixture(
    webhelpers.html`<dees-input-wysiwyg></dees-input-wysiwyg>`
  );

  // Import a code block
  editor.importBlocks([
    { id: 'code-1', type: 'code', content: 'function test() {', metadata: { language: 'javascript' } }
  ]);

  await editor.updateComplete;
  await new Promise(resolve => setTimeout(resolve, 100));

  // Focus code block - code blocks use .code-editor instead of .block.code
  const codeBlockWrapper = editor.shadowRoot?.querySelector('[data-block-id="code-1"]');
  const codeBlockComponent = codeBlockWrapper?.querySelector('dees-wysiwyg-block') as DeesWysiwygBlock;
  const codeBlockContainer = codeBlockComponent?.shadowRoot?.querySelector('.wysiwyg-block-container') as HTMLElement;
  const codeElement = codeBlockContainer?.querySelector('.code-editor') as HTMLElement;

  expect(codeElement).toBeTruthy();

  // Focus and set cursor at end
  codeElement.focus();
  const textNode = codeElement.firstChild;
  if (textNode && textNode.nodeType === Node.TEXT_NODE) {
    const range = document.createRange();
    const selection = window.getSelection();
    range.setStart(textNode, textNode.textContent?.length || 0);
    range.setEnd(textNode, textNode.textContent?.length || 0);
    selection?.removeAllRanges();
    selection?.addRange(range);
  }

  await new Promise(resolve => setTimeout(resolve, 100));

  // Press Tab to insert spaces
  const tabEvent = new KeyboardEvent('keydown', {
    key: 'Tab',
    code: 'Tab',
    bubbles: true,
    cancelable: true,
    composed: true
  });

  codeElement.dispatchEvent(tabEvent);
  await new Promise(resolve => setTimeout(resolve, 200));

  // Check if spaces were inserted
  const updatedContent = codeElement.textContent || '';
  expect(updatedContent).toContain('  '); // Tab should insert 2 spaces

  console.log('Tab in code block test complete');
});

tap.test('Keyboard: ArrowUp/Down navigation', async () => {
  const editor: DeesInputWysiwyg = await webhelpers.fixture(
    webhelpers.html`<dees-input-wysiwyg></dees-input-wysiwyg>`
  );

  // Import multiple blocks
  editor.importBlocks([
    { id: 'nav-1', type: 'paragraph', content: 'First line' },
    { id: 'nav-2', type: 'paragraph', content: 'Second line' },
    { id: 'nav-3', type: 'paragraph', content: 'Third line' }
  ]);

  await editor.updateComplete;
  await new Promise(resolve => setTimeout(resolve, 100));

  // Verify blocks were created
  expect(editor.blocks.length).toEqual(3);

  // Focus second block
  const secondBlockWrapper = editor.shadowRoot?.querySelector('[data-block-id="nav-2"]');
  const secondBlockComponent = secondBlockWrapper?.querySelector('dees-wysiwyg-block') as DeesWysiwygBlock;
  const secondBlockContainer = secondBlockComponent?.shadowRoot?.querySelector('.wysiwyg-block-container') as HTMLElement;
  const secondParagraph = secondBlockContainer?.querySelector('.block.paragraph') as HTMLElement;

  expect(secondParagraph).toBeTruthy();
  secondParagraph.focus();
  await new Promise(resolve => setTimeout(resolve, 100));

  // Verify keyboard handler exists
  expect(editor.keyboardHandler).toBeTruthy();

  // Press ArrowUp - event is dispatched (focus change may not occur in synthetic events)
  const arrowUpEvent = new KeyboardEvent('keydown', {
    key: 'ArrowUp',
    code: 'ArrowUp',
    bubbles: true,
    cancelable: true,
    composed: true
  });

  secondParagraph.dispatchEvent(arrowUpEvent);
  await new Promise(resolve => setTimeout(resolve, 200));

  // Get first block references
  const firstBlockWrapper = editor.shadowRoot?.querySelector('[data-block-id="nav-1"]');
  const firstBlockComponent = firstBlockWrapper?.querySelector('dees-wysiwyg-block') as DeesWysiwygBlock;
  const firstBlockContainer = firstBlockComponent?.shadowRoot?.querySelector('.wysiwyg-block-container') as HTMLElement;
  const firstParagraph = firstBlockContainer?.querySelector('.block.paragraph') as HTMLElement;

  expect(firstParagraph).toBeTruthy();

  // Note: Synthetic keyboard events don't reliably trigger native browser focus changes
  // in automated tests. The handler is invoked but focus may not actually move.
  // This test verifies the structure exists and events can be dispatched.

  console.log('ArrowUp/Down navigation test complete');
});

tap.test('Keyboard: Formatting shortcuts', async () => {
  const editor: DeesInputWysiwyg = await webhelpers.fixture(
    webhelpers.html`<dees-input-wysiwyg></dees-input-wysiwyg>`
  );
  
  // Import a paragraph
  editor.importBlocks([
    { id: 'format-1', type: 'paragraph', content: 'Test formatting' }
  ]);
  
  await editor.updateComplete;
  await new Promise(resolve => setTimeout(resolve, 100));
  
  // Focus and select text
  const blockWrapper = editor.shadowRoot?.querySelector('[data-block-id="format-1"]');
  const blockComponent = blockWrapper?.querySelector('dees-wysiwyg-block') as DeesWysiwygBlock;
  const blockContainer = blockComponent?.shadowRoot?.querySelector('.wysiwyg-block-container') as HTMLElement;
  const paragraph = blockContainer?.querySelector('.block.paragraph') as HTMLElement;
  
  paragraph.focus();
  
  // Select "formatting"
  const textNode = paragraph.firstChild;
  if (textNode && textNode.nodeType === Node.TEXT_NODE) {
    const range = document.createRange();
    const selection = window.getSelection();
    range.setStart(textNode, 5); // After "Test "
    range.setEnd(textNode, 15); // After "formatting"
    selection?.removeAllRanges();
    selection?.addRange(range);
  }
  
  await new Promise(resolve => setTimeout(resolve, 100));
  
  // Press Cmd/Ctrl+B for bold
  const boldEvent = new KeyboardEvent('keydown', {
    key: 'b',
    code: 'KeyB',
    metaKey: true, // Use metaKey for Mac, ctrlKey for Windows/Linux
    bubbles: true,
    cancelable: true,
    composed: true
  });
  
  paragraph.dispatchEvent(boldEvent);
  await new Promise(resolve => setTimeout(resolve, 200));
  
  // Check if bold was applied
  const content = paragraph.innerHTML;
  expect(content).toContain('<strong>') || expect(content).toContain('<b>');
  
  console.log('Formatting shortcuts test complete');
});

export default tap.start();