import React, { useEffect, useRef } from 'react'
import { selectLocalParticipantIsConnected, selectRemoteParticipants, useChat } from '../../store'
import { useZocksStore } from '../../app'
import { setMessageRecipient } from '../../store/chat/chatSlice'
import { useZocksDispatch } from '../../app/hooks'
import { getClassName, getMergedClassNames } from '../common'
import { ChatInputProps, SplitChatProps } from './models'
import { CustomizableChatInput, RecipientSelector } from './ChatInput'
import { ChatMessageWithAvatar } from './ChatMessage'
import { ParticipantNotConnected } from './ParticipantNotConnected'
import zocksStyle from './SplitChat.module.scss'

export const SplitChat: React.FC<SplitChatProps> = ({ styles, chatActions, dismiss, components }) => {
  const dispatch = useZocksDispatch()
  const {
    sendPublicMessage,
    sendPrivateMessage,
    uploadAttachment,
    getAttachmentLocation,
    publicChatMessages,
    privateChatMessages,
    messageRecipient,
  } = useChat(chatActions)
  const localParticipantIsConnected = useZocksStore(selectLocalParticipantIsConnected)
  const remoteParticipants = useZocksStore(selectRemoteParticipants)

  const messagesEndRef = useRef<HTMLDivElement>(null)
  const scrollToBottom = () => {
    messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' })
  }

  useEffect(() => {
    scrollToBottom()
  }, [publicChatMessages, privateChatMessages])

  const ChatMessageElement = components?.ChatMessage ?? ChatMessageWithAvatar
  const ChatInputElement = components?.ChatInput ?? ChatInputWithoutRecipientSelector
  const RecipientSelectorElement = components?.RecipientSelector ?? RecipientSelector
  const ParticipantNotConnectedElement = components?.ParticipantNotConnected ?? ParticipantNotConnected

  const handleRecipientSelected = (recipientId: string) => {
    dispatch(setMessageRecipient(recipientId))
  }

  const selectedRecipientMessages = !messageRecipient ? publicChatMessages : privateChatMessages[messageRecipient] || []
  const mergedStyles = getMergedClassNames(zocksStyle, styles)

  if (!localParticipantIsConnected) {
    return <ParticipantNotConnectedElement styles={mergedStyles} />
  }

  return (
    <div className={getClassName('chat', mergedStyles)}>
      {dismiss && (
        <div className={getClassName('chat__header', mergedStyles)}>
          <button onClick={dismiss} aria-label='Dismiss' />
        </div>
      )}
      <div className={getClassName('chat__main-container', mergedStyles)}>
        <RecipientSelectorElement
          onRecipientSelected={handleRecipientSelected}
          remoteParticipants={remoteParticipants}
          styles={zocksStyle}
        />
        <div className={getClassName('chat__messages-container', mergedStyles)}>
          <div className={getClassName('chat__messages-scroll', mergedStyles)}>
            {selectedRecipientMessages.map((chatMessage, idx) => {
              const showAvatar =
                idx === selectedRecipientMessages.length - 1 ||
                selectedRecipientMessages[idx + 1].from.id !== chatMessage.from.id
              return (
                <ChatMessageElement
                  key={idx}
                  chatMessage={chatMessage}
                  showAvatar={showAvatar}
                  getAttachmentLocation={getAttachmentLocation}
                  styles={mergedStyles}
                />
              )
            })}
            <div ref={messagesEndRef} />
          </div>
        </div>
        <div className={getClassName('chat__footer', mergedStyles)}>
          <ChatInputElement
            messageRecipient={messageRecipient}
            remoteParticipants={remoteParticipants}
            sendPublicMessage={sendPublicMessage}
            sendPrivateMessage={sendPrivateMessage}
            uploadAttachment={uploadAttachment}
            styles={mergedStyles}
          />
        </div>
      </div>
    </div>
  )
}

const ChatInputWithoutRecipientSelector: React.FC<ChatInputProps> = (props) => {
  return <CustomizableChatInput {...props} components={{ RecipientSelector: () => null }} />
}
