import { describe, it, expect } from 'vitest'
import { render, screen } from '@testing-library/react'
import { MarkdownBody } from '../../chat/markdown'

describe('MarkdownBody', () => {
  // ============================================================
  // 基础渲染测试
  // ============================================================
  describe('基础渲染', () => {
    it('应正确渲染组件', () => {
      const { container } = render(<MarkdownBody>Hello World</MarkdownBody>)
      expect(container.firstChild).toBeInTheDocument()
    })

    it('应设置正确的 displayName', () => {
      expect(MarkdownBody.displayName).toBe('MarkdownBody')
    })

    it('应渲染普通文本', () => {
      render(<MarkdownBody>Simple text content</MarkdownBody>)
      expect(screen.getByText('Simple text content')).toBeInTheDocument()
    })
  })

  // ============================================================
  // 段落渲染测试
  // ============================================================
  describe('段落 (p)', () => {
    it('应渲染段落为 p 元素', () => {
      const { container } = render(<MarkdownBody>A paragraph</MarkdownBody>)
      expect(container.querySelector('p')).toBeInTheDocument()
    })

    it('段落应有正确的样式类', () => {
      const { container } = render(<MarkdownBody>Styled paragraph</MarkdownBody>)
      const p = container.querySelector('p')
      expect(p).toHaveClass('text-sm')
      expect(p).toHaveClass('text-text')
    })
  })

  // ============================================================
  // 标题渲染测试
  // ============================================================
  describe('标题 (h1-h6)', () => {
    it('应渲染 h1 标题', () => {
      const { container } = render(<MarkdownBody># Heading 1</MarkdownBody>)
      const h1 = container.querySelector('h1')
      expect(h1).toBeInTheDocument()
      expect(h1).toHaveTextContent('Heading 1')
    })

    it('应渲染 h2 标题', () => {
      const { container } = render(<MarkdownBody>## Heading 2</MarkdownBody>)
      const h2 = container.querySelector('h2')
      expect(h2).toBeInTheDocument()
      expect(h2).toHaveTextContent('Heading 2')
    })

    it('应渲染 h3 标题', () => {
      const { container } = render(<MarkdownBody>### Heading 3</MarkdownBody>)
      const h3 = container.querySelector('h3')
      expect(h3).toBeInTheDocument()
    })

    it('h1 应有正确的样式', () => {
      const { container } = render(<MarkdownBody># Title</MarkdownBody>)
      const h1 = container.querySelector('h1')
      expect(h1).toHaveClass('text-4xl')
      expect(h1).toHaveClass('font-medium')
    })

    it('h2 应有边框样式', () => {
      const { container } = render(<MarkdownBody>## Section</MarkdownBody>)
      const h2 = container.querySelector('h2')
      expect(h2).toHaveClass('border-b')
    })
  })

  // ============================================================
  // 列表渲染测试
  // ============================================================
  describe('列表 (ul/ol)', () => {
    it('应渲染无序列表', () => {
      const { container } = render(
        <MarkdownBody>{`- Item 1\n- Item 2\n- Item 3`}</MarkdownBody>
      )
      const ul = container.querySelector('ul')
      expect(ul).toBeInTheDocument()
      expect(ul).toHaveClass('list-disc')
    })

    it('应渲染有序列表', () => {
      const { container } = render(
        <MarkdownBody>{`1. First\n2. Second\n3. Third`}</MarkdownBody>
      )
      const ol = container.querySelector('ol')
      expect(ol).toBeInTheDocument()
      expect(ol).toHaveClass('list-decimal')
    })

    it('列表项应正确渲染', () => {
      const { container } = render(
        <MarkdownBody>{`- Apple\n- Banana`}</MarkdownBody>
      )
      const items = container.querySelectorAll('li')
      expect(items).toHaveLength(2)
    })
  })

  // ============================================================
  // 代码渲染测试
  // ============================================================
  describe('代码 (code/pre)', () => {
    it('应渲染行内代码', () => {
      const { container } = render(
        <MarkdownBody>Use `npm install` to install</MarkdownBody>
      )
      const code = container.querySelector('code')
      expect(code).toBeInTheDocument()
      expect(code).toHaveTextContent('npm install')
    })

    it('行内代码应有背景样式', () => {
      const { container } = render(
        <MarkdownBody>Run `test` command</MarkdownBody>
      )
      const code = container.querySelector('code')
      expect(code).toHaveClass('bg-fill-tertiary')
      expect(code).toHaveClass('rounded')
    })

    it('应渲染代码块', () => {
      const { container } = render(
        <MarkdownBody>{`\`\`\`javascript\nconst x = 1;\n\`\`\``}</MarkdownBody>
      )
      const pre = container.querySelector('pre')
      expect(pre).toBeInTheDocument()
    })

    it('代码块应包含在滚动容器中', () => {
      const { container } = render(
        <MarkdownBody>{`\`\`\`js\ncode\n\`\`\``}</MarkdownBody>
      )
      // Scrollbar 组件包裹
      const scrollContainer = container.querySelector('[class*="overflow"]')
      expect(scrollContainer).toBeInTheDocument()
    })
  })

  // ============================================================
  // 引用渲染测试
  // ============================================================
  describe('引用 (blockquote)', () => {
    it('应渲染引用块', () => {
      const { container } = render(
        <MarkdownBody>{'> This is a quote'}</MarkdownBody>
      )
      const blockquote = container.querySelector('blockquote')
      expect(blockquote).toBeInTheDocument()
    })

    it('引用块应有边框样式', () => {
      const { container } = render(
        <MarkdownBody>{'> Quote text'}</MarkdownBody>
      )
      const blockquote = container.querySelector('blockquote')
      expect(blockquote).toHaveClass('border-l-2')
      expect(blockquote).toHaveClass('italic')
    })
  })

  // ============================================================
  // 链接渲染测试
  // ============================================================
  describe('链接 (a)', () => {
    it('应渲染链接', () => {
      render(<MarkdownBody>[Click me](https://example.com)</MarkdownBody>)
      const link = screen.getByRole('link')
      expect(link).toBeInTheDocument()
      expect(link).toHaveTextContent('Click me')
    })

    it('链接应在新标签页打开', () => {
      render(<MarkdownBody>[Link](https://example.com)</MarkdownBody>)
      const link = screen.getByRole('link')
      expect(link).toHaveAttribute('target', '_blank')
      expect(link).toHaveAttribute('rel', 'noopener noreferrer')
    })

    it('链接应有正确的 href', () => {
      render(<MarkdownBody>[Test](https://test.com)</MarkdownBody>)
      const link = screen.getByRole('link')
      expect(link).toHaveAttribute('href', 'https://test.com')
    })
  })

  // ============================================================
  // 强调渲染测试
  // ============================================================
  describe('强调 (strong/em)', () => {
    it('应渲染粗体', () => {
      const { container } = render(
        <MarkdownBody>**Bold text**</MarkdownBody>
      )
      const strong = container.querySelector('strong')
      expect(strong).toBeInTheDocument()
      expect(strong).toHaveTextContent('Bold text')
    })

    it('应渲染斜体', () => {
      const { container } = render(
        <MarkdownBody>*Italic text*</MarkdownBody>
      )
      const em = container.querySelector('em')
      expect(em).toBeInTheDocument()
      expect(em).toHaveTextContent('Italic text')
    })

    it('粗体应有正确样式', () => {
      const { container } = render(
        <MarkdownBody>**Strong**</MarkdownBody>
      )
      const strong = container.querySelector('strong')
      expect(strong).toHaveClass('font-semibold')
    })

    it('斜体应有正确样式', () => {
      const { container } = render(
        <MarkdownBody>*Emphasis*</MarkdownBody>
      )
      const em = container.querySelector('em')
      expect(em).toHaveClass('italic')
    })
  })

  // ============================================================
  // 水平线渲染测试
  // ============================================================
  describe('水平线 (hr)', () => {
    it('应渲染水平线', () => {
      const { container } = render(
        <MarkdownBody>{`Above\n\n---\n\nBelow`}</MarkdownBody>
      )
      const hr = container.querySelector('hr')
      expect(hr).toBeInTheDocument()
    })
  })

  // ============================================================
  // 表格渲染测试 (GFM)
  // ============================================================
  describe('表格 (GFM)', () => {
    it('应渲染表格', () => {
      const tableMarkdown = `
| Name | Age |
|------|-----|
| Alice | 25 |
| Bob | 30 |
      `
      const { container } = render(<MarkdownBody>{tableMarkdown}</MarkdownBody>)
      expect(container.querySelector('table')).toBeInTheDocument()
    })

    it('应渲染表头', () => {
      const tableMarkdown = `
| Header1 | Header2 |
|---------|---------|
| Cell1 | Cell2 |
      `
      const { container } = render(<MarkdownBody>{tableMarkdown}</MarkdownBody>)
      const thead = container.querySelector('thead')
      expect(thead).toBeInTheDocument()
    })

    it('应渲染表体', () => {
      const tableMarkdown = `
| A | B |
|---|---|
| 1 | 2 |
      `
      const { container } = render(<MarkdownBody>{tableMarkdown}</MarkdownBody>)
      const tbody = container.querySelector('tbody')
      expect(tbody).toBeInTheDocument()
    })

    it('表格应在滚动容器中', () => {
      const tableMarkdown = `
| Col1 | Col2 |
|------|------|
| Data | Data |
      `
      const { container } = render(<MarkdownBody>{tableMarkdown}</MarkdownBody>)
      // Scrollbar 组件包裹
      const scrollContainer = container.querySelector('[class*="border"]')
      expect(scrollContainer).toBeInTheDocument()
    })
  })

  // ============================================================
  // 任务列表测试 (GFM)
  // ============================================================
  describe('任务列表 (GFM)', () => {
    it('应渲染任务列表', () => {
      const taskList = `
- [ ] Unchecked
- [x] Checked
      `
      const { container } = render(<MarkdownBody>{taskList}</MarkdownBody>)
      const checkboxes = container.querySelectorAll('input[type="checkbox"]')
      expect(checkboxes.length).toBeGreaterThan(0)
    })

    it('任务列表应无圆点样式', () => {
      const taskList = `
- [ ] Task 1
- [x] Task 2
      `
      const { container } = render(<MarkdownBody>{taskList}</MarkdownBody>)
      const ul = container.querySelector('ul')
      expect(ul).toHaveClass('list-none')
    })
  })

  // ============================================================
  // className 测试
  // ============================================================
  describe('className', () => {
    it('应合并自定义 className', () => {
      const { container } = render(
        <MarkdownBody className="custom-markdown">Content</MarkdownBody>
      )
      expect(container.firstChild).toHaveClass('custom-markdown')
    })

    it('根元素应有 markdown-body 类', () => {
      const { container } = render(
        <MarkdownBody>Content</MarkdownBody>
      )
      expect(container.firstChild).toHaveClass('markdown-body')
    })
  })

  // ============================================================
  // 复杂内容测试
  // ============================================================
  describe('复杂内容', () => {
    it('应正确渲染混合内容', () => {
      const complexMarkdown = `
# Title

A paragraph with **bold** and *italic* text.

- List item 1
- List item 2

\`\`\`js
const x = 1;
\`\`\`

> A quote

[A link](https://example.com)
      `
      const { container } = render(<MarkdownBody>{complexMarkdown}</MarkdownBody>)

      expect(container.querySelector('h1')).toBeInTheDocument()
      expect(container.querySelector('p')).toBeInTheDocument()
      expect(container.querySelector('strong')).toBeInTheDocument()
      expect(container.querySelector('em')).toBeInTheDocument()
      expect(container.querySelector('ul')).toBeInTheDocument()
      expect(container.querySelector('pre')).toBeInTheDocument()
      expect(container.querySelector('blockquote')).toBeInTheDocument()
      expect(container.querySelector('a')).toBeInTheDocument()
    })

    it('应处理空字符串', () => {
      const { container } = render(<MarkdownBody>{''}</MarkdownBody>)
      expect(container.firstChild).toBeInTheDocument()
    })

    it('应处理纯空白字符串', () => {
      const { container } = render(<MarkdownBody>{'   '}</MarkdownBody>)
      expect(container.firstChild).toBeInTheDocument()
    })
  })
})
