import React from 'react'
import { expect } from 'chai'
import sinon from 'sinon'
import { screen, render, fireEvent } from '@testing-library/react'

import PreviewLogsPaneEntry from '../../../../../frontend/js/features/preview/components/preview-logs-pane-entry.js'

describe('<PreviewLogsPaneEntry />', function() {
  const level = 'error'

  it('renders a configurable aria-label', function() {
    const sampleAriaLabel = 'lorem ipsum dolor sit amet'
    render(
      <PreviewLogsPaneEntry entryAriaLabel={sampleAriaLabel} level={level} />
    )
    screen.getByLabelText(sampleAriaLabel)
  })

  describe('logs pane source location link', function() {
    const file = 'foo.tex'
    const line = 42
    const column = 21
    const onSourceLocationClick = sinon.stub()

    afterEach(function() {
      onSourceLocationClick.reset()
    })

    it('renders both file and line', function() {
      render(
        <PreviewLogsPaneEntry sourceLocation={{ file, line }} level={level} />
      )
      screen.getByRole('button', {
        name: `Navigate to log position in source code: ${file}, ${line}`
      })
    })

    it('renders only file when line information is not available', function() {
      render(<PreviewLogsPaneEntry sourceLocation={{ file }} level={level} />)
      screen.getByRole('button', {
        name: `Navigate to log position in source code: ${file}`
      })
    })

    it('does not render when file information is not available', function() {
      render(<PreviewLogsPaneEntry level={level} />)
      expect(
        screen.queryByRole('button', {
          name: `Navigate to log position in source code: `
        })
      ).to.not.exist
    })

    it('calls the callback with file, line and column on click', function() {
      render(
        <PreviewLogsPaneEntry
          sourceLocation={{ file, line, column }}
          level={level}
          onSourceLocationClick={onSourceLocationClick}
        />
      )
      const linkToSourceButton = screen.getByRole('button', {
        name: `Navigate to log position in source code: ${file}, ${line}`
      })

      fireEvent.click(linkToSourceButton)
      expect(onSourceLocationClick).to.be.calledOnce
      expect(onSourceLocationClick).to.be.calledWith({
        file,
        line,
        column
      })
    })
  })

  describe('logs pane entry raw contents', function() {
    const rawContent = 'foo bar latex error stuff baz'

    it('renders collapsed contents by default', function() {
      render(<PreviewLogsPaneEntry rawContent={rawContent} level={level} />)
      screen.getByText(rawContent)
      screen.getByRole('button', {
        name: 'Expand'
      })
    })

    it('supports expanding contents', function() {
      render(<PreviewLogsPaneEntry rawContent={rawContent} level={level} />)
      screen.getByText(rawContent)
      const expandCollapseBtn = screen.getByRole('button', {
        name: 'Expand'
      })
      fireEvent.click(expandCollapseBtn)
      screen.getByRole('button', {
        name: 'Collapse'
      })
    })

    it('should not render at all when there are no log contents', function() {
      const { container } = render(<PreviewLogsPaneEntry level={level} />)
      expect(container.querySelector('.log-entry-content')).to.not.exist
    })
  })

  describe('formatted content', function() {
    const rawContent = 'foo bar latex error stuff baz'
    const formattedContentText = 'foo bar baz'
    const formattedContent = <>{formattedContentText}</>
    const infoURL = 'www.overleaf.com/learn/latex'

    it('renders the hint', function() {
      render(
        <PreviewLogsPaneEntry
          rawContent={rawContent}
          formattedContent={formattedContent}
          extraInfoURL={infoURL}
          level={level}
        />
      )
      screen.getByText(formattedContentText)
    })

    it('renders the link to learn more', function() {
      render(
        <PreviewLogsPaneEntry
          rawContent={rawContent}
          formattedContent={formattedContent}
          extraInfoURL={infoURL}
          level={level}
        />
      )
      screen.getByRole('link', { name: 'Learn more' })
    })

    it('does not render the link when it is not available', function() {
      render(
        <PreviewLogsPaneEntry
          rawContent={rawContent}
          formattedContent={formattedContent}
          level={level}
        />
      )
      expect(screen.queryByRole('link', { name: 'Learn more' })).to.not.exist
    })
  })
})
