import clsx from 'clsx'
import {DisplayUser} from 'common/api/user-types'
import {ChatMessage} from 'common/chat-message'
import {compassUserId} from 'common/profiles/constants'
import {first, last} from 'lodash'
import {Dispatch, memo, SetStateAction, useRef, useState} from 'react'
import {MessageActions} from 'web/components/chat/message-actions'
import {MessageReactions} from 'web/components/chat/message-reactions'
import {Col} from 'web/components/layout/col'
import {Modal, MODAL_CLASS} from 'web/components/layout/modal'
import {Row} from 'web/components/layout/row'
import {MultipleOrSingleAvatars} from 'web/components/multiple-or-single-avatars'
import {RelativeTimestamp} from 'web/components/relative-timestamp'
import {Avatar} from 'web/components/widgets/avatar'
import {Content} from 'web/components/widgets/editor'
import {UserAvatarAndBadge} from 'web/components/widgets/user-link'

export function ChatMessageItem(props: {
  chats: ChatMessage[]
  currentUser: DisplayUser | undefined | null
  otherUser?: DisplayUser | null
  onReplyClick?: (chat: ChatMessage) => void
  beforeSameUser: boolean
  firstOfUser: boolean
  hideAvatar: boolean
  onRequestEdit?: (chat: ChatMessage) => void
  setMessages?: Dispatch<SetStateAction<ChatMessage[] | undefined>>
}) {
  const {
    chats,
    onReplyClick,
    currentUser,
    otherUser,
    beforeSameUser,
    firstOfUser,
    hideAvatar,
    onRequestEdit,
    setMessages,
  } = props
  const chat = first(chats)

  const [emojiOpenForId, setEmojiOpenForId] = useState<number | null>(null)
  const [emojiKey, setEmojiKey] = useState(0)
  const longPressTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null)
  const hasMovedRef = useRef(false)
  const lastPositionRef = useRef<{x: number; y: number} | null>(null)

  if (!chat) return null

  // console.log('chat', chat)

  const isMe = currentUser?.id === chat.userId
  const {username, avatarUrl, id} =
    !isMe && otherUser
      ? otherUser
      : isMe && currentUser
        ? currentUser
        : {username: '', avatarUrl: undefined, id: ''}

  const startLongPress = (messageId: number) => {
    hasMovedRef.current = false
    lastPositionRef.current = null
    if (longPressTimerRef.current) clearTimeout(longPressTimerRef.current)
    longPressTimerRef.current = setTimeout(() => {
      if (!hasMovedRef.current) {
        setEmojiOpenForId(messageId)
        setEmojiKey((k) => k + 1)
      }
    }, 1000)
  }

  const cancelLongPress = () => {
    if (longPressTimerRef.current) {
      clearTimeout(longPressTimerRef.current)
      longPressTimerRef.current = null
    }
  }

  const handleMouseMove = (e: React.MouseEvent) => {
    const currentPos = {x: e.clientX, y: e.clientY}
    if (lastPositionRef.current) {
      const dx = Math.abs(currentPos.x - lastPositionRef.current.x)
      const dy = Math.abs(currentPos.y - lastPositionRef.current.y)
      if (dx > 5 || dy > 5) {
        hasMovedRef.current = true
      }
    }
    lastPositionRef.current = currentPos
  }

  return (
    <Row
      className={clsx(
        '@container items-end justify-start gap-1',
        isMe && 'flex-row-reverse',
        firstOfUser ? 'mt-2' : 'mt-1',
      )}
    >
      {!isMe && !hideAvatar && (
        <MessageAvatar
          beforeSameUser={beforeSameUser}
          username={username}
          userAvatarUrl={avatarUrl}
          userId={id}
        />
      )}
      <Col className="sm:max-w-[calc(100vw-6rem)] md:max-w-[70%]">
        <Col className="gap-1">
          {chats.map((chat) => (
            <div
              className={clsx('group flex items-end gap-1', isMe && 'flex-row-reverse')}
              key={chat.id}
            >
              <div className="group relative">
                <Row>
                  <div
                    className={clsx(
                      'rounded-3xl px-3 py-2',
                      chat.visibility !== 'system_status' && '',
                      chat.visibility === 'system_status'
                        ? 'bg-canvas-50 italic'
                        : isMe
                          ? 'bg-primary-200 items-end self-end rounded-r-none group-first:rounded-tr-3xl'
                          : 'bg-canvas-50 items-start self-start rounded-l-none group-first:rounded-tl-3xl',
                    )}
                    onMouseDown={() => startLongPress(chat.id)}
                    onMouseUp={cancelLongPress}
                    onMouseLeave={cancelLongPress}
                    onMouseMove={handleMouseMove}
                    onTouchStart={() => startLongPress(chat.id)}
                    onTouchEnd={cancelLongPress}
                    onTouchCancel={cancelLongPress}
                    data-testid="conversation-message"
                  >
                    <Content
                      size={'sm'}
                      content={chat.content}
                      key={chat.id}
                      className={'!text-ink-1000'}
                    />
                  </div>
                </Row>
                {/* Hidden host for emoji picker, opened via long-press */}
                <div className={clsx('absolute -mt-2', isMe ? 'right-40' : 'left-40')}>
                  <MessageActions
                    message={{
                      id: chat.id,
                      userId: chat.userId,
                      content: chat.content,
                      isEdited: chat.isEdited,
                      reactions: chat.reactions,
                    }}
                    setMessages={setMessages}
                    hideTrigger
                    openEmojiPickerKey={emojiOpenForId === chat.id ? emojiKey : undefined}
                  />
                </div>
                <MessageReactions
                  message={{
                    id: chat.id,
                    reactions: chat.reactions as Record<string, string[]> | undefined,
                  }}
                  className={clsx('ml-2', isMe ? 'justify-end' : 'justify-start')}
                  setMessages={setMessages}
                />
              </div>
              <Col className="mb-2 mr-1 text-xs">
                {chat.visibility !== 'system_status' && (
                  <Row className={'items-center gap-3'}>
                    {/*{!isMe &&*/}
                    {/*    <Link*/}
                    {/*        href={'/' + username}*/}
                    {/*        className="text-ink-500 dark:text-ink-600 pl-3 text-sm"*/}
                    {/*    >*/}
                    {/*      {name}*/}
                    {/*    </Link>*/}
                    {/*}*/}
                    {onReplyClick && (
                      <div className="flex items-center gap-1">
                        {/*<button*/}
                        {/*  className="text-ink-400 hover:text-ink-600"*/}
                        {/*  onClick={() => onReplyClick?.(chat)}*/}
                        {/*>*/}
                        {/*  <ReplyIcon className="h-4 w-4"/>*/}
                        {/*</button>*/}
                        <MessageActions
                          message={{
                            id: chat.id,
                            userId: chat.userId,
                            content: chat.content,
                            isEdited: chat.isEdited,
                            reactions: chat.reactions,
                          }}
                          setMessages={setMessages}
                          onRequestEdit={() => onRequestEdit?.(chat)}
                          className="text-xs group-last:block"
                        />
                      </div>
                    )}
                  </Row>
                )}
                <RelativeTimestamp
                  time={chat.createdTime}
                  shortened
                  className="hidden text-xs group-last:block"
                />
              </Col>
            </div>
          ))}
        </Col>
      </Col>
      <div className={clsx(isMe ? 'pr-1' : '', 'pb-2')}></div>
    </Row>
  )
}

export const SystemChatMessageItem = memo(function SystemChatMessageItem(props: {
  chats: ChatMessage[]
  otherUsers: DisplayUser[] | undefined
}) {
  const {chats, otherUsers} = props
  const chat = last(chats)
  const [showUsers, setShowUsers] = useState(false)
  if (!chat) return null
  const totalUsers = otherUsers?.length || 1
  const hideAvatar =
    (chat.visibility === 'system_status' && chat.userId === compassUserId && chats.length === 1) ||
    totalUsers < 2
  return (
    <Row className={clsx('flex-row-reverse items-center gap-1')}>
      <Row className="grow" />
      <Col className={clsx('grow-y justify-end pb-2')}>
        <RelativeTimestamp time={chat.createdTime} shortened className="text-xs" />
      </Col>
      <Col className="max-w-[calc(100vw-6rem)] md:max-w-[80%]">
        <Col className={clsx(' bg-canvas-50  px-1 py-2 text-sm italic')}>
          {totalUsers > 1 ? (
            <span>
              {totalUsers} user{totalUsers > 1 ? 's' : ''} joined the chat!
            </span>
          ) : (
            <>
              <Content content={chat.content} size={'sm'} />
              {chat.visibility !== 'system_status' && (
                <div className="invisible absolute right-0 top-0 -mt-2 flex translate-x-2 items-center opacity-0 transition-all group-hover:visible group-hover:translate-x-0 group-hover:opacity-100">
                  <MessageActions
                    message={{
                      id: chat.id,
                      userId: chat.userId,
                      content: chat.content,
                      isEdited: chat.isEdited,
                      reactions: chat.reactions,
                    }}
                  />
                </div>
              )}
            </>
          )}
        </Col>
      </Col>
      {!hideAvatar && (
        <MultipleOrSingleAvatars
          size={'xs'}
          spacing={0.3}
          startLeft={0.6}
          avatars={otherUsers || []}
          onClick={() => setShowUsers(true)}
        />
      )}
      {showUsers && (
        <MultiUserModal
          showUsers={showUsers}
          setShowUsers={setShowUsers}
          otherUsers={otherUsers ?? []}
        />
      )}
    </Row>
  )
})
export const MultiUserModal = (props: {
  showUsers: boolean
  setShowUsers: (show: boolean) => void
  otherUsers: DisplayUser[]
}) => {
  const {showUsers, setShowUsers, otherUsers} = props
  return (
    <Modal open={showUsers} setOpen={setShowUsers}>
      <Col className={clsx(MODAL_CLASS)}>
        {otherUsers?.map((user) => (
          <Row key={user.id} className={'w-full items-center justify-start gap-2'}>
            <UserAvatarAndBadge user={user} />
          </Row>
        ))}
      </Col>
    </Modal>
  )
}

function MessageAvatar(props: {
  beforeSameUser: boolean
  userAvatarUrl?: string
  username?: string
  userId: string
}) {
  const {beforeSameUser, userAvatarUrl, username} = props
  return (
    <Col
      className={clsx(
        beforeSameUser ? 'pointer-events-none invisible' : '',
        'grow-y justify-end pb-2 pr-1',
      )}
    >
      <Avatar avatarUrl={userAvatarUrl} username={username} size="xs" />
    </Col>
  )
}
