import { Provider } from 'react-redux'
import { render, screen } from '@testing-library/react'
import { configureStore } from '@reduxjs/toolkit'
import { ChatMessageModel, ChatMessageType } from '../../../store/chat/models'
import { zocksStoreConfig } from '../../../app/store'
import { setLocalParticipantId } from '../../../store/session/sessionSlice'
import { ChatMessageWithParticipantInfo } from './ChatMessageWithParticipantInfo'

const testPublicChatMessage: ChatMessageModel = {
  type: ChatMessageType.PUBLIC,
  message: 'test public chat message',
  timestamp: 1,
  from: {
    id: 'testSenderId',
    name: 'Test Sender',
  },
}

const testPrivateChatMessage: ChatMessageModel = {
  type: ChatMessageType.PRIVATE,
  message: 'test private chat message',
  timestamp: 1,
  from: {
    id: 'testSenderId',
    name: 'Test Sender',
  },
  to: {
    id: 'testLocalParticipantId',
    name: 'Test Local Participant',
  },
}

const renderWithState = (chatMessage: ChatMessageModel, showParticipantInfo: boolean = true) => {
  const store = configureStore(zocksStoreConfig)
  store.dispatch(setLocalParticipantId('testLocalParticipantId'))
  render(
    <Provider store={store}>
      <ChatMessageWithParticipantInfo
        chatMessage={chatMessage}
        showParticipantInfo={showParticipantInfo}
        getAttachmentLocation={jest.fn()}
      />
    </Provider>
  )
}

test('renders the header text and the message for public messages when the sender is the local participant', () => {
  renderWithState({
    ...testPublicChatMessage,
    from: {
      id: 'testLocalParticipantId',
      name: 'Test Local Participant',
    },
  })

  expect(screen.getByText('Me')).toBeInTheDocument()
  expect(screen.getByText('test public chat message')).toBeInTheDocument()
})

test('renders the header text and the message for public messages when the sender is not the local participant', () => {
  renderWithState(testPublicChatMessage)

  expect(screen.getByText('Test Sender')).toBeInTheDocument()
  expect(screen.getByText('test public chat message')).toBeInTheDocument()
})

test('renders the header text and the message for private messages when the sender is the local participant', () => {
  renderWithState({
    ...testPrivateChatMessage,
    from: testPrivateChatMessage.to!,
    to: testPrivateChatMessage.from,
  })

  expect(screen.getByText('Me To Test Sender')).toBeInTheDocument()
  expect(screen.getByText('test private chat message')).toBeInTheDocument()
})

test('renders the header text and the message for private messages when the sender is not the local participant', () => {
  renderWithState(testPrivateChatMessage)

  expect(screen.getByText('Test Sender To Me')).toBeInTheDocument()
  expect(screen.getByText('test private chat message')).toBeInTheDocument()
})

test('renders only the chat message if info should not be displayed for public messages', () => {
  renderWithState(testPublicChatMessage, false)

  expect(screen.getByText('test public chat message')).toBeInTheDocument()
  expect(screen.queryByText('Test Sender')).not.toBeInTheDocument()
})

test('renders only the chat message if info should not be displayed for private messages', () => {
  renderWithState(testPrivateChatMessage, false)

  expect(screen.getByText('test private chat message')).toBeInTheDocument()
  expect(screen.queryByText('Test Sender')).not.toBeInTheDocument()
})

test('renders an anchor tag with a link if the chat message contains a link', () => {
  renderWithState({ ...testPublicChatMessage, message: 'message with a link: https://example.com' })

  expect(screen.getByText('message with a link:', { exact: false })).toBeInTheDocument()
  expect(screen.getByRole('link', { name: 'https://example.com' })).toBeInTheDocument()
})

test('renders the attachment when given', () => {
  renderWithState({
    ...testPublicChatMessage,
    attachment: { fileId: 'test', fileName: 'test', fileSize: 42, contentType: 'text/plain' },
  })

  expect(screen.getByText('Download')).toBeInTheDocument()
})
