import { describe, test, expect } from 'vitest'
import { render, screen } from '@testing-library/react'
import { MarkdownUI } from './markdown-ui'

describe('MarkdownUI', () => {
  test('renders plain text without markdown', () => {
    render(<MarkdownUI>Plain text content</MarkdownUI>)
    expect(screen.getByText('Plain text content')).toBeTruthy()
  })

  test('renders empty string', () => {
    const { container } = render(<MarkdownUI>{''}</MarkdownUI>)
    expect(container).toBeTruthy()
  })

  test('renders h1 as Typography variant h4', () => {
    render(<MarkdownUI># Heading 1</MarkdownUI>)
    const heading = screen.getByText('Heading 1')
    expect(heading.tagName).toBe('H4')
  })

  test('renders h2 as Typography variant h5', () => {
    render(<MarkdownUI>## Heading 2</MarkdownUI>)
    const heading = screen.getByText('Heading 2')
    expect(heading.tagName).toBe('H5')
  })

  test('renders h3 as Typography variant h6', () => {
    render(<MarkdownUI>### Heading 3</MarkdownUI>)
    const heading = screen.getByText('Heading 3')
    expect(heading.tagName).toBe('H6')
  })

  test('renders multiple headings of different levels', () => {
    render(
      <MarkdownUI>
        {`# H1 Heading
## H2 Heading
### H3 Heading`}
      </MarkdownUI>,
    )
    expect(screen.getByText('H1 Heading')).toBeTruthy()
    expect(screen.getByText('H2 Heading')).toBeTruthy()
    expect(screen.getByText('H3 Heading')).toBeTruthy()
  })

  test('renders paragraph as Typography', () => {
    render(<MarkdownUI>This is a paragraph.</MarkdownUI>)
    expect(screen.getByText('This is a paragraph.')).toBeTruthy()
  })

  test('renders multiple paragraphs', () => {
    render(
      <MarkdownUI>
        {`First paragraph.

Second paragraph.

Third paragraph.`}
      </MarkdownUI>,
    )
    expect(screen.getByText('First paragraph.')).toBeTruthy()
    expect(screen.getByText('Second paragraph.')).toBeTruthy()
    expect(screen.getByText('Third paragraph.')).toBeTruthy()
  })

  test('renders link with href attribute', () => {
    render(<MarkdownUI>[Link text](https://example.com)</MarkdownUI>)
    const link = screen.getByText('Link text')
    expect(link.tagName).toBe('A')
    expect(link.getAttribute('href')).toBe('https://example.com')
  })

  test('renders link with target="_blank" by default', () => {
    render(<MarkdownUI>[External link](https://example.com)</MarkdownUI>)
    const link = screen.getByText('External link')
    expect(link.getAttribute('target')).toBe('_blank')
  })

  test('renders link with rel="noopener noreferrer" by default', () => {
    render(<MarkdownUI>[Secure link](https://example.com)</MarkdownUI>)
    const link = screen.getByText('Secure link')
    expect(link.getAttribute('rel')).toBe('noopener noreferrer')
  })

  test('renders multiple links', () => {
    render(
      <MarkdownUI>
        [Link 1](https://example1.com) and [Link 2](https://example2.com)
      </MarkdownUI>,
    )
    expect(screen.getByText('Link 1')).toBeTruthy()
    expect(screen.getByText('Link 2')).toBeTruthy()
  })

  test('renders unordered list', () => {
    render(
      <MarkdownUI>
        {`- Item 1
- Item 2
- Item 3`}
      </MarkdownUI>,
    )
    expect(screen.getByText('Item 1')).toBeTruthy()
    expect(screen.getByText('Item 2')).toBeTruthy()
    expect(screen.getByText('Item 3')).toBeTruthy()
  })

  test('renders ordered list', () => {
    render(
      <MarkdownUI>
        {`1. First item
2. Second item
3. Third item`}
      </MarkdownUI>,
    )
    expect(screen.getByText('First item')).toBeTruthy()
    expect(screen.getByText('Second item')).toBeTruthy()
    expect(screen.getByText('Third item')).toBeTruthy()
  })

  test('renders nested lists', () => {
    render(
      <MarkdownUI>
        {`- Parent 1
  - Child 1
  - Child 2
- Parent 2`}
      </MarkdownUI>,
    )
    expect(screen.getByText('Parent 1')).toBeTruthy()
    expect(screen.getByText('Child 1')).toBeTruthy()
    expect(screen.getByText('Child 2')).toBeTruthy()
    expect(screen.getByText('Parent 2')).toBeTruthy()
  })

  test('renders list items as MUI ListItem components', () => {
    render(<MarkdownUI>{`- List item`}</MarkdownUI>)
    const listItem = screen.getByText('List item')
    expect(listItem.classList.contains('MuiListItem-root')).toBe(true)
  })

  test('renders complex markdown with mixed elements', () => {
    render(
      <MarkdownUI>
        {`# Main Title

This is a paragraph with [a link](https://example.com).

## Subsection

- Bullet point 1
- Bullet point 2

### Details

Another paragraph.`}
      </MarkdownUI>,
    )
    expect(screen.getByText('Main Title')).toBeTruthy()
    expect(screen.getByText(/This is a paragraph/)).toBeTruthy()
    expect(screen.getByText('a link')).toBeTruthy()
    expect(screen.getByText('Subsection')).toBeTruthy()
    expect(screen.getByText('Bullet point 1')).toBeTruthy()
    expect(screen.getByText('Bullet point 2')).toBeTruthy()
    expect(screen.getByText('Details')).toBeTruthy()
    expect(screen.getByText('Another paragraph.')).toBeTruthy()
  })

  test('renders markdown with special characters', () => {
    render(<MarkdownUI>Text with `code` and **bold** and *italic*</MarkdownUI>)
    expect(screen.getByText('code')).toBeTruthy()
    expect(screen.getByText('bold')).toBeTruthy()
    expect(screen.getByText('italic')).toBeTruthy()
  })

  test('handles long markdown content', () => {
    const longContent = `# Long Content

${'Paragraph. '.repeat(100)}

## Section 2

${'- Item\n'.repeat(50)}`
    render(<MarkdownUI>{longContent}</MarkdownUI>)
    expect(screen.getByText('Long Content')).toBeTruthy()
    expect(screen.getByText('Section 2')).toBeTruthy()
  })

  test('renders markdown with line breaks', () => {
    render(
      <MarkdownUI>
        {`Line 1

Line 2


Line 3`}
      </MarkdownUI>,
    )
    expect(screen.getByText('Line 1')).toBeTruthy()
    expect(screen.getByText('Line 2')).toBeTruthy()
    expect(screen.getByText('Line 3')).toBeTruthy()
  })

  test('renders markdown with inline code', () => {
    render(<MarkdownUI>Use `npm install` to install dependencies.</MarkdownUI>)
    expect(screen.getByText('npm install')).toBeTruthy()
    expect(screen.getByText(/Use/)).toBeTruthy()
    expect(screen.getByText(/to install dependencies/)).toBeTruthy()
  })

  test('renders markdown with emphasis', () => {
    render(<MarkdownUI>This is *emphasized* text</MarkdownUI>)
    expect(screen.getByText('emphasized')).toBeTruthy()
  })

  test('renders markdown with strong emphasis', () => {
    render(<MarkdownUI>This is **strong** text</MarkdownUI>)
    expect(screen.getByText('strong')).toBeTruthy()
  })

  test('renders only specified heading levels (h1-h3)', () => {
    render(
      <MarkdownUI>
        {`# H1
## H2
### H3
#### H4
##### H5
###### H6`}
      </MarkdownUI>,
    )
    expect(screen.getByText('H1')).toBeTruthy()
    expect(screen.getByText('H2')).toBeTruthy()
    expect(screen.getByText('H3')).toBeTruthy()
    expect(screen.getByText('H4')).toBeTruthy()
    expect(screen.getByText('H5')).toBeTruthy()
    expect(screen.getByText('H6')).toBeTruthy()
  })

  test('handles markdown with escaped characters', () => {
    render(<MarkdownUI>Escaped \\* asterisk and \\# hash</MarkdownUI>)
    expect(screen.getByText(/asterisk/)).toBeTruthy()
    expect(screen.getByText(/hash/)).toBeTruthy()
  })

  test('renders markdown with numeric content', () => {
    render(
      <MarkdownUI>
        {`1. First: 100
2. Second: 200
3. Third: 300`}
      </MarkdownUI>,
    )
    expect(screen.getByText(/First: 100/)).toBeTruthy()
    expect(screen.getByText(/Second: 200/)).toBeTruthy()
    expect(screen.getByText(/Third: 300/)).toBeTruthy()
  })

  test('preserves whitespace in code elements', () => {
    render(<MarkdownUI>`code with spaces`</MarkdownUI>)
    expect(screen.getByText(/code with.*spaces/)).toBeTruthy()
  })

  test('renders multiple consecutive headings', () => {
    render(
      <MarkdownUI>
        {`# Heading 1
## Heading 2
### Heading 3`}
      </MarkdownUI>,
    )
    expect(screen.getByText('Heading 1').tagName).toBe('H4')
    expect(screen.getByText('Heading 2').tagName).toBe('H5')
    expect(screen.getByText('Heading 3').tagName).toBe('H6')
  })

  test('renders links within paragraphs', () => {
    render(
      <MarkdownUI>
        This paragraph contains [a link](https://example.com) in the middle.
      </MarkdownUI>,
    )
    const link = screen.getByText('a link')
    expect(link.tagName).toBe('A')
    expect(screen.getByText(/This paragraph contains/)).toBeTruthy()
  })

  test('renders mixed list types', () => {
    render(
      <MarkdownUI>
        {`Unordered:
- Item A
- Item B

Ordered:
1. First
2. Second`}
      </MarkdownUI>,
    )
    expect(screen.getByText('Item A')).toBeTruthy()
    expect(screen.getByText('Item B')).toBeTruthy()
    expect(screen.getByText('First')).toBeTruthy()
    expect(screen.getByText('Second')).toBeTruthy()
  })

  test('renders content with all supported markdown features', () => {
    render(
      <MarkdownUI>
        {`# Title

Paragraph with **bold**, *italic*, and \`code\`.

## List Section

- Item 1 with [link](https://example.com)
- Item 2

### Ordered

1. First
2. Second

End paragraph.`}
      </MarkdownUI>,
    )
    expect(screen.getByText('Title')).toBeTruthy()
    expect(screen.getByText('bold')).toBeTruthy()
    expect(screen.getByText('italic')).toBeTruthy()
    expect(screen.getByText('code')).toBeTruthy()
    expect(screen.getByText('List Section')).toBeTruthy()
    expect(screen.getByText(/Item 1/)).toBeTruthy()
    expect(screen.getByText('link')).toBeTruthy()
    expect(screen.getByText('Item 2')).toBeTruthy()
    expect(screen.getByText('Ordered')).toBeTruthy()
    expect(screen.getByText('First')).toBeTruthy()
    expect(screen.getByText('Second')).toBeTruthy()
    expect(screen.getByText('End paragraph.')).toBeTruthy()
  })
})
