import { render } from '@testing-library/react';

import { RichTextEditor } from '../rich-text-editor';
import type { CrystallizeRichText, CrystallizeRichTextNode } from '../types/crystallize-rich-text-types';
import { sleep } from './utils';

function paragraphWithText(textContent: string): CrystallizeRichTextNode {
  return {
    kind: 'block',
    type: 'paragraph',
    textContent,
  };
}

/**
 * In these tests, we are ensuring that the conversion from
 * CrystallizeRichText to Lexial back to CrystallizeRichText works
 * like expected.
 */

const dataTypes: { name: string; model: CrystallizeRichText }[] = [
  {
    name: 'unordered-list',
    model: [
      {
        kind: 'block',
        type: 'unordered-list',
        children: [
          {
            textContent: 'rabbit',
            type: 'list-item',
            kind: 'block',
          },
        ],
      },
    ],
  },
  {
    name: 'ordered-list',
    model: [
      {
        kind: 'block',
        type: 'ordered-list',
        children: [
          {
            textContent: 'rabbit',
            type: 'list-item',
            kind: 'block',
          },
        ],
      },
    ],
  },
  // Headings
  ...[1, 2, 3, 4, 5, 6].map(v => ({
    name: 'heading' + v,
    model: [
      {
        kind: 'block',
        type: 'heading' + v,
        textContent: 'Hi there',
      },
    ] as CrystallizeRichText,
  })),
  {
    name: 'paragraph',
    model: [
      {
        kind: 'block',
        type: 'paragraph',
        textContent: 'Hi there',
      },
    ],
  },
  {
    name: 'horizontal-line',
    model: [
      {
        kind: 'block',
        type: 'horizontal-line',
      },
    ],
  },
  {
    name: 'code (inline)',
    model: [
      {
        kind: 'block',
        type: 'paragraph',
        children: [
          {
            type: 'code',
            kind: 'inline',
            textContent: 'I am code',
          },
        ],
      },
    ],
  },
  {
    name: 'code (block)',
    model: [
      {
        kind: 'block',
        type: 'preformatted',
        children: [
          {
            type: 'code',
            kind: 'block',
            textContent: 'const aVariable = 42;',
            metadata: { language: 'javascript' },
          },
        ],
      },
    ],
  },
  {
    name: 'link',
    model: [
      {
        kind: 'block',
        type: 'paragraph',
        children: [
          {
            kind: 'inline',
            type: 'link',
            textContent: 'I am link',
            metadata: {
              href: '#',
              rel: '...',
              target: '...',
            },
          },
        ],
      },
    ],
  },
  {
    name: 'table',
    model: [
      {
        kind: 'block',
        type: 'table',
        children: [
          {
            kind: 'block',
            type: 'table-row',
            children: [
              {
                type: 'table-cell',
                kind: 'inline',
                children: [paragraphWithText('Hi from ')],
              },
              {
                type: 'table-cell',
                kind: 'inline',
                children: [paragraphWithText('a table')],
              },
            ],
          },
        ],
      },
    ],
  },
  {
    name: 'inline text formatting',
    model: [
      {
        kind: 'block',
        type: 'paragraph',
        children: ['underlined', 'emphasized', 'strong', 'superscripted', 'subscripted', 'deleted'].map(
          type =>
            ({
              kind: 'inline',
              textContent: type,
              type,
            } as CrystallizeRichTextNode),
        ),
      },
    ],
  },
  {
    name: 'quote',
    model: [
      {
        kind: 'block',
        type: 'quote',
        textContent: 'Simon says: ...',
      },
    ],
  },
  {
    name: 'Multiple inline formats',
    model: [
      {
        type: 'paragraph',
        kind: 'block',
        children: [
          {
            kind: 'inline',
            type: 'strong',
            children: [
              {
                kind: 'inline',
                textContent: 'placed',
                type: 'emphasized',
              },
            ],
          },
        ],
      },
    ],
  },
];

describe('RichTextEditor model conversions', () => {
  dataTypes.forEach(dataType => {
    it('correctly converts ' + dataType.name, async () => {
      const onChange = vi.fn();

      render(<RichTextEditor initialData={dataType.model} onChange={onChange} triggerOnChangeOnAutoFocus autoFocus />);

      await sleep(1);

      expect(onChange).toBeCalledTimes(1);
      expect(onChange).toBeCalledWith(dataType.model);
    });
  });
});
