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

// Initialize the element
DeesInputWysiwyg;

tap.test('wysiwyg drag and drop should work correctly', async () => {
  const element = document.createElement('dees-input-wysiwyg');
  document.body.appendChild(element);

  // Wait for element to be ready
  await element.updateComplete;

  // Set initial content with multiple blocks
  element.blocks = [
    { id: 'block1', type: 'paragraph', content: 'First paragraph' },
    { id: 'block2', type: 'heading-2', content: 'Test Heading' },
    { id: 'block3', type: 'paragraph', content: 'Second paragraph' },
  ];
  element.renderBlocksProgrammatically();

  await element.updateComplete;
  // Wait for nested block components to also complete their updates
  await new Promise(resolve => setTimeout(resolve, 50));

  // Check that blocks are rendered
  const editorContent = element.shadowRoot!.querySelector('.editor-content') as HTMLDivElement;
  expect(editorContent).toBeTruthy();

  const blockWrappers = editorContent.querySelectorAll('.block-wrapper');
  expect(blockWrappers.length).toEqual(3);

  // Test drag handles exist for non-divider blocks
  const dragHandles = editorContent.querySelectorAll('.drag-handle');
  expect(dragHandles.length).toEqual(3);

  // Get references to specific blocks
  const firstBlock = editorContent.querySelector('[data-block-id="block1"]') as HTMLElement;
  const secondBlock = editorContent.querySelector('[data-block-id="block2"]') as HTMLElement;
  const firstDragHandle = firstBlock.querySelector('.drag-handle') as HTMLElement;

  expect(firstBlock).toBeTruthy();
  expect(secondBlock).toBeTruthy();
  expect(firstDragHandle).toBeTruthy();

  // Verify drag drop handler exists
  expect(element.dragDropHandler).toBeTruthy();
  expect(element.dragDropHandler.dragState).toBeTruthy();

  // Test drag initialization - synthetic DragEvents may not fully work in all browsers
  console.log('Testing drag initialization...');

  // Create drag event
  const dragStartEvent = new DragEvent('dragstart', {
    dataTransfer: new DataTransfer(),
    clientY: 100,
    bubbles: true
  });

  // Simulate drag start
  firstDragHandle.dispatchEvent(dragStartEvent);

  // Wait for setTimeout in drag start
  await new Promise(resolve => setTimeout(resolve, 50));

  // Note: Synthetic DragEvents may not fully initialize drag state in all test environments
  // The test verifies the structure and that events can be dispatched
  console.log('Drag state after start:', element.dragDropHandler.dragState.draggedBlockId);

  // Test drag end cleanup
  const dragEndEvent = new DragEvent('dragend', {
    bubbles: true
  });

  document.dispatchEvent(dragEndEvent);

  // Wait for cleanup
  await new Promise(resolve => setTimeout(resolve, 150));

  // Clean up
  document.body.removeChild(element);
});

tap.test('wysiwyg drag and drop visual feedback', async () => {
  const element = document.createElement('dees-input-wysiwyg');
  document.body.appendChild(element);
  
  await element.updateComplete;
  
  // Set initial content
  element.blocks = [
    { id: 'block1', type: 'paragraph', content: 'Block 1' },
    { id: 'block2', type: 'paragraph', content: 'Block 2' },
    { id: 'block3', type: 'paragraph', content: 'Block 3' },
  ];
  element.renderBlocksProgrammatically();

  await element.updateComplete;
  // Wait for nested block components to also complete their updates
  await new Promise(resolve => setTimeout(resolve, 50));

  const editorContent = element.shadowRoot!.querySelector('.editor-content') as HTMLDivElement;
  const block1 = editorContent.querySelector('[data-block-id="block1"]') as HTMLElement;
  const dragHandle1 = block1.querySelector('.drag-handle') as HTMLElement;
  
  // Start dragging block 1
  const dragStartEvent = new DragEvent('dragstart', {
    dataTransfer: new DataTransfer(),
    clientY: 50,
    bubbles: true
  });
  
  dragHandle1.dispatchEvent(dragStartEvent);
  
  // Wait for dragging class
  await new Promise(resolve => setTimeout(resolve, 20));
  
  // Simulate dragging down
  const dragOverEvent = new DragEvent('dragover', {
    dataTransfer: new DataTransfer(),
    clientY: 150, // Move down past block 2
    bubbles: true,
    cancelable: true
  });
  
  // Trigger the global drag over handler
  element.dragDropHandler['handleGlobalDragOver'](dragOverEvent);
  
  // Check that transform is applied to dragged block
  const transform = block1.style.transform;
  console.log('Dragged block transform:', transform);
  expect(transform).toContain('translateY');
  
  // Check drop indicator position
  const dropIndicator = editorContent.querySelector('.drop-indicator') as HTMLElement;
  if (dropIndicator) {
    const indicatorStyle = dropIndicator.style;
    console.log('Drop indicator position:', indicatorStyle.top, 'display:', indicatorStyle.display);
  }
  
  // Clean up
  document.body.removeChild(element);
});

export default tap.start();