'use client'

import { useState, useRef, useEffect, useCallback } from 'react'
import { FiSend, FiSmile } from 'react-icons/fi'
import { useTranslation } from 'react-i18next'

import { CHAT_EMOJI_MESSAGE_PX } from '@/app/room/_components/chat/chatEmojis'
import MentionDropdown from './MentionDropdown'
import { parseChatCommand } from './utils'

interface MentionUser {
    userId: string
    name: string
    avatarUrl?: string | null
}

export default function WriteBar({
    writeAreaRef,
    draft,
    setDraft,
    placeholder,
    emojiBtnRef,
    onEmojiToggle,
    emojiTip,
    tipClassName,
    onSend,
    disabled = false,
    banInfo,
    mentionUsers = [],
    isMobile = false,
    onCommand,
    chatDisabled = false,
    isSuperAdmin = false,
    onEmojiClick,
    emojiItems,
}: {
    writeAreaRef: React.RefObject<HTMLDivElement>
    draft: string
    setDraft: (v: string) => void
    placeholder: string
    emojiBtnRef: React.RefObject<HTMLButtonElement>
    onEmojiToggle: () => void
    emojiTip: string
    tipClassName: string
    onSend: () => void
    disabled?: boolean
    banInfo?: { isPermanent: boolean; expiresAt: number | null; remainingMs: number | null; reason?: string | null } | null
    mentionUsers?: MentionUser[]
    isMobile?: boolean
    onCommand?: (command: { type: 'user'; args: string[] }) => void
    chatDisabled?: boolean
    isSuperAdmin?: boolean
    onEmojiClick?: React.RefObject<{ insertEmoji: (code: string) => void } | null>
    emojiItems?: Array<{ id: string; alt: string; code: string; src: string }>
}) {
    // Translations
    const { t } = useTranslation()

    // States
    const [mentionQuery, setMentionQuery] = useState('')
    const [mentionIndex, setMentionIndex] = useState(0)
    const [showMentionDropdown, setShowMentionDropdown] = useState(false)
    const [mentionPosition, setMentionPosition] = useState({ top: 0, left: 0 })

    // Refs
    const mentionDropdownRef = useRef<HTMLDivElement>(null)


    const isBanned = banInfo !== null && banInfo !== undefined
    const isDisabled = disabled || isBanned || (chatDisabled && !isSuperAdmin)
    const banReason = isBanned && banInfo.reason ? String(banInfo.reason).trim() : ''
    const banMessage = isBanned
        ? banInfo.isPermanent
            ? t('room.ban.permanentBan')
            : t('room.ban.banMinutes', { minutes: banInfo.remainingMs ? Math.ceil(banInfo.remainingMs / (1000 * 60)) : 0 })
        : (chatDisabled && !isSuperAdmin)
            ? t('room.chat.disabled')
            : placeholder
    const everyoneOption: MentionUser = {
        userId: '@everyone',
        name: t('room.mention.everyone'),
        avatarUrl: null,
    }

    const filteredMentionUsers = (() => {
        const allUsers = [everyoneOption, ...(mentionUsers || [])]
        if (!mentionQuery) return allUsers
        return allUsers.filter((user) =>
            user.name.toLowerCase().includes(mentionQuery.toLowerCase())
        )
    })()

    const updateMentionPosition = useCallback(() => {
        if (!writeAreaRef.current) return
        const selection = window.getSelection()
        if (!selection || selection.rangeCount === 0) return
        const range = selection.getRangeAt(0)
        const rect = range.getBoundingClientRect()
        const containerElement = writeAreaRef.current.parentElement
        if (!containerElement) return
        const containerRect = containerElement.getBoundingClientRect()
        const relativeLeft = Math.max(0, Math.min(rect.left - containerRect.left, containerRect.width - 280))
        setMentionPosition({
            top: 0,
            left: relativeLeft,
        })
    }, [writeAreaRef])

    const MAX_TEXT_LENGTH = 200

    const hasContent = useCallback(() => {
        if (!writeAreaRef.current) return false
        if (writeAreaRef.current.childNodes.length === 0) return false
        if (writeAreaRef.current.textContent?.trim().length > 0) return true
        for (let i = 0; i < writeAreaRef.current.childNodes.length; i++) {
            const node = writeAreaRef.current.childNodes[i]
            if (node.nodeType === Node.ELEMENT_NODE) {
                const el = node as HTMLElement
                if (el.tagName === 'IMG' || el.getAttribute('data-mention') === 'true') {
                    return true
                }
            }
        }
        return false
    }, [writeAreaRef])

    const handleInput = (e: React.FormEvent<HTMLDivElement>) => {
        if (isDisabled) return
        const text = e.currentTarget.textContent || ''
        if (text.length > MAX_TEXT_LENGTH) {
            e.preventDefault()
            const selection = window.getSelection()
            if (selection && selection.rangeCount > 0) {
                const cursorPosition = getCaretPosition(e.currentTarget)
                const truncatedText = text.substring(0, MAX_TEXT_LENGTH)
                e.currentTarget.textContent = truncatedText
                const newCursorPosition = Math.min(cursorPosition, MAX_TEXT_LENGTH)
                const newRange = document.createRange()
                const textNode = e.currentTarget.firstChild
                if (textNode && textNode.nodeType === Node.TEXT_NODE) {
                    newRange.setStart(textNode, newCursorPosition)
                    newRange.collapse(true)
                    selection.removeAllRanges()
                    selection.addRange(newRange)
                }
            } else {
                e.currentTarget.textContent = text.substring(0, MAX_TEXT_LENGTH)
            }
            setDraft(text.substring(0, MAX_TEXT_LENGTH))
            return
        }
        setDraft(text)
        const selection = window.getSelection()
        if (!selection || selection.rangeCount === 0) {
            setShowMentionDropdown(false)
            return
        }
        const cursorPosition = getCaretPosition(e.currentTarget)
        const textBeforeCursor = text.substring(0, cursorPosition)
        const mentionMatch = textBeforeCursor.match(/@(\w*)$/)
        if (mentionMatch) {
            const query = mentionMatch[1]
            setMentionQuery(query)
            setShowMentionDropdown(true)
            setMentionIndex(0)
            requestAnimationFrame(() => {
                updateMentionPosition()
            })
        } else {
            setShowMentionDropdown(false)
        }
    }

    const getCaretPosition = useCallback((element: HTMLElement): number => {
        const selection = window.getSelection()
        if (!selection || selection.rangeCount === 0) return 0
        const range = selection.getRangeAt(0)
        const preCaretRange = range.cloneRange()
        preCaretRange.selectNodeContents(element)
        preCaretRange.setEnd(range.endContainer, range.endOffset)
        return preCaretRange.toString().length
    }, [])

    const insertMention = (user: MentionUser) => {
        if (!writeAreaRef.current) return
        const selection = window.getSelection()
        if (!selection || selection.rangeCount === 0) return
        const range = selection.getRangeAt(0)
        const text = writeAreaRef.current.textContent || ''
        const cursorPosition = getCaretPosition(writeAreaRef.current)
        const textBeforeCursor = text.substring(0, cursorPosition)
        const mentionMatch = textBeforeCursor.match(/@(\w*)$/)
        if (mentionMatch) {
            const mentionText = `@${user.name} `
            const textAfterCursor = text.substring(cursorPosition)
            const newTextLength = textBeforeCursor.length - mentionMatch[0].length + mentionText.length + textAfterCursor.length
            if (newTextLength > MAX_TEXT_LENGTH) {
                return
            }
            range.setStart(range.startContainer, range.startOffset - mentionMatch[0].length)
            range.deleteContents()
            const tagSpan = document.createElement('span')
            const isEveryone = user.userId === '@everyone'
            tagSpan.className = isEveryone
                ? 'inline-flex items-center px-2 py-0.5 rounded-md bg-yellow-100 dark:bg-yellow-900/30 text-yellow-700 dark:text-yellow-300 text-sm font-medium mx-0.5'
                : 'inline-flex items-center px-2 py-0.5 rounded-md bg-blue-100 dark:bg-blue-900/30 text-blue-700 dark:text-blue-300 text-sm font-medium mx-0.5'
            tagSpan.setAttribute('data-mention', 'true')
            tagSpan.setAttribute('data-user-id', user.userId)
            tagSpan.setAttribute('data-user-name', user.name)
            tagSpan.setAttribute('contenteditable', 'false')
            tagSpan.textContent = `@${user.name}`
            range.insertNode(tagSpan)
            const spaceNode = document.createTextNode(' ')
            const newRange = document.createRange()
            newRange.setStartAfter(tagSpan)
            newRange.collapse(true)
            newRange.insertNode(spaceNode)
            newRange.setStartAfter(spaceNode)
            newRange.collapse(true)
            selection.removeAllRanges()
            selection.addRange(newRange)
            const newText = writeAreaRef.current.textContent || ''
            setDraft(newText)
            setShowMentionDropdown(false)
        }
    }

    const insertEmoji = useCallback((emojiCode: string) => {
        if (!writeAreaRef.current || isDisabled) return
        const emojiItem = emojiItems?.find((item) => item.code === emojiCode)
        if (!emojiItem) return
        const currentText = writeAreaRef.current.textContent || ''
        if (currentText.length >= MAX_TEXT_LENGTH) {
            return
        }
        if (document.activeElement !== writeAreaRef.current) {
            writeAreaRef.current.focus()
        }
        const selection = window.getSelection()
        if (!selection) return
        if (selection.rangeCount === 0 || !writeAreaRef.current.contains(selection.anchorNode)) {
            const range = document.createRange()
            range.selectNodeContents(writeAreaRef.current)
            range.collapse(false)
            selection.removeAllRanges()
            selection.addRange(range)
        }
        const img = document.createElement('img')
        img.src = emojiItem.src
        img.alt = emojiItem.alt
        img.setAttribute('data-emoji-code', emojiItem.code)
        img.setAttribute('data-emoji-src', emojiItem.src)
        img.width = CHAT_EMOJI_MESSAGE_PX
        img.height = CHAT_EMOJI_MESSAGE_PX
        img.className = 'inline-block align-middle object-contain'
        img.style.width = `${CHAT_EMOJI_MESSAGE_PX}px`
        img.style.height = `${CHAT_EMOJI_MESSAGE_PX}px`
        img.style.verticalAlign = 'middle'
        img.style.display = 'inline-block'
        if (selection.rangeCount === 0) {
            writeAreaRef.current.appendChild(img)
            const newRange = document.createRange()
            newRange.setStartAfter(img)
            newRange.collapse(true)
            selection.removeAllRanges()
            selection.addRange(newRange)
        } else {
            const range = selection.getRangeAt(0)
            range.deleteContents()
            range.insertNode(img)
            range.setStartAfter(img)
            range.collapse(true)
            selection.removeAllRanges()
            selection.addRange(range)
        }
        const newText = writeAreaRef.current.textContent || ''
        setDraft(newText)
    }, [isDisabled, setDraft, emojiItems, writeAreaRef])

    useEffect(() => {
        if (onEmojiClick && typeof onEmojiClick === 'object' && 'current' in onEmojiClick) {
            ; (onEmojiClick as any).current = { insertEmoji }
        }
    }, [onEmojiClick, insertEmoji])

    const handlePaste = (e: React.ClipboardEvent<HTMLDivElement>) => {
        if (isDisabled) {
            e.preventDefault()
            return
        }
        e.preventDefault()
        const text = e.clipboardData.getData('text/plain')
        if (!text) return
        const selection = window.getSelection()
        if (!selection || selection.rangeCount === 0) return
        const currentText = writeAreaRef.current?.textContent || ''
        const range = selection.getRangeAt(0)
        const cursorPosition = getCaretPosition(writeAreaRef.current!)
        const textBeforeCursor = currentText.substring(0, cursorPosition)
        const textAfterCursor = currentText.substring(cursorPosition)
        const newTextLength = textBeforeCursor.length + text.length + textAfterCursor.length
        let textToInsert = text
        if (newTextLength > MAX_TEXT_LENGTH) {
            const availableLength = MAX_TEXT_LENGTH - textBeforeCursor.length - textAfterCursor.length
            if (availableLength <= 0) {
                return
            }
            textToInsert = text.substring(0, availableLength)
        }
        range.deleteContents()
        const textNode = document.createTextNode(textToInsert)
        range.insertNode(textNode)

        range.setStartAfter(textNode)
        range.collapse(true)
        selection.removeAllRanges()
        selection.addRange(range)
        if (writeAreaRef.current) {
            const newText = writeAreaRef.current.textContent || ''
            setDraft(newText)
        }
    }

    const handleKeyDown = (e: React.KeyboardEvent<HTMLDivElement>) => {
        if (isDisabled) {
            e.preventDefault()
            return
        }
        if (e.key === 'Backspace' && writeAreaRef.current) {
            const selection = window.getSelection()
            if (selection && selection.rangeCount > 0) {
                const range = selection.getRangeAt(0)
                const startContainer = range.startContainer
                if (startContainer.nodeType === Node.TEXT_NODE && startContainer.textContent === '') {
                    const prevSibling = startContainer.previousSibling
                    if (prevSibling && prevSibling.nodeType === Node.ELEMENT_NODE) {
                        const element = prevSibling as HTMLElement
                        if (element.getAttribute('data-mention') === 'true') {
                            e.preventDefault()
                            element.remove()
                            if (startContainer.parentNode) {
                                startContainer.parentNode.removeChild(startContainer)
                            }
                            const newText = writeAreaRef.current.textContent || ''
                            setDraft(newText)
                            return
                        }
                    }
                }
                let node: Node | null = startContainer
                while (node && node !== writeAreaRef.current) {
                    if (node.nodeType === Node.ELEMENT_NODE) {
                        const element = node as HTMLElement
                        if (element.getAttribute('data-mention') === 'true') {
                            e.preventDefault()
                            element.remove()
                            const newText = writeAreaRef.current.textContent || ''
                            setDraft(newText)
                            return
                        }
                    }
                    node = node.parentNode
                }
            }
        }
        if (showMentionDropdown && filteredMentionUsers.length > 0) {
            if (e.key === 'ArrowDown') {
                e.preventDefault()
                setMentionIndex((prev) => (prev + 1) % filteredMentionUsers.length)
                return
            }
            if (e.key === 'ArrowUp') {
                e.preventDefault()
                setMentionIndex((prev) => (prev - 1 + filteredMentionUsers.length) % filteredMentionUsers.length)
                return
            }
            if (e.key === 'Enter' || e.key === 'Tab') {
                e.preventDefault()
                insertMention(filteredMentionUsers[mentionIndex])
                return
            }
            if (e.key === 'Escape') {
                e.preventDefault()
                setShowMentionDropdown(false)
                return
            }
        }
        if (e.key === 'Enter' && !e.shiftKey) {
            e.preventDefault()
            const text = writeAreaRef.current?.textContent || ''
            const command = parseChatCommand(text)
            if (command && onCommand) {
                onCommand(command)
                if (writeAreaRef.current) {
                    writeAreaRef.current.textContent = ''
                    setDraft('')
                }
                return
            }
            onSend()
        }
    }

    useEffect(() => {
        const element = writeAreaRef.current
        if (!element || isDisabled) return
        const checkCursorPosition = () => {
            const selection = window.getSelection()
            if (!selection || selection.rangeCount === 0) return
            const range = selection.getRangeAt(0)
            let node: Node | null = range.startContainer
            while (node && node !== element) {
                if (node.nodeType === Node.ELEMENT_NODE) {
                    const el = node as HTMLElement
                    if (el.getAttribute('data-mention') === 'true') {
                        const newRange = document.createRange()
                        newRange.setStartAfter(el)
                        newRange.collapse(true)
                        selection.removeAllRanges()
                        selection.addRange(newRange)
                        return
                    }
                }
                node = node.parentNode
            }
        }

        const handleSelectionChange = () => {
            if (writeAreaRef.current && document.activeElement === writeAreaRef.current) {
                checkCursorPosition()
            }
        }

        const handleBeforeInput = (e: InputEvent) => {
            if (!writeAreaRef.current) return
            const selection = window.getSelection()
            if (!selection || selection.rangeCount === 0) return
            const range = selection.getRangeAt(0)
            let node: Node | null = range.startContainer
            while (node && node !== writeAreaRef.current) {
                if (node.nodeType === Node.ELEMENT_NODE) {
                    const element = node as HTMLElement
                    if (element.getAttribute('data-mention') === 'true') {
                        e.preventDefault()
                        const newRange = document.createRange()
                        newRange.setStartAfter(element)
                        newRange.collapse(true)
                        selection.removeAllRanges()
                        selection.addRange(newRange)
                        return
                    }
                }
                node = node.parentNode
            }
            const currentText = writeAreaRef.current.textContent || ''
            const cursorPosition = getCaretPosition(writeAreaRef.current)
            const textBeforeCursor = currentText.substring(0, cursorPosition)
            const textAfterCursor = currentText.substring(cursorPosition)
            const inputData = e.data || ''
            const newTextLength = textBeforeCursor.length + inputData.length + textAfterCursor.length
            if (newTextLength > MAX_TEXT_LENGTH) {
                e.preventDefault()
                const availableLength = MAX_TEXT_LENGTH - textBeforeCursor.length - textAfterCursor.length
                if (availableLength > 0) {
                    const textToInsert = inputData.substring(0, availableLength)
                    const textNode = document.createTextNode(textToInsert)
                    range.deleteContents()
                    range.insertNode(textNode)
                    range.setStartAfter(textNode)
                    range.collapse(true)
                    selection.removeAllRanges()
                    selection.addRange(range)
                    const newText = writeAreaRef.current.textContent || ''
                    setDraft(newText)
                }
            }
        }

        document.addEventListener('selectionchange', handleSelectionChange)
        element.addEventListener('beforeinput', handleBeforeInput)

        return () => {
            document.removeEventListener('selectionchange', handleSelectionChange)
            element.removeEventListener('beforeinput', handleBeforeInput)
        }
    }, [isDisabled, writeAreaRef, setDraft, getCaretPosition])

    useEffect(() => {
        if (!showMentionDropdown) return

        const element = writeAreaRef.current
        const handleClickOutside = (e: MouseEvent) => {
            if (mentionDropdownRef.current && !mentionDropdownRef.current.contains(e.target as Node) && element && !element.contains(e.target as Node)) {
                setShowMentionDropdown(false)
            }
        }
        const handleSelectionChange = () => {
            if (showMentionDropdown) {
                updateMentionPosition()
            }
        }
        document.addEventListener('mousedown', handleClickOutside)
        document.addEventListener('selectionchange', handleSelectionChange)
        return () => {
            document.removeEventListener('mousedown', handleClickOutside)
            document.removeEventListener('selectionchange', handleSelectionChange)
        }
    }, [showMentionDropdown, updateMentionPosition, writeAreaRef])

    const showBanReasonLine = isBanned && Boolean(banReason)

    return (
        <div
            className={`relative w-full rounded-xl bg-[#f6f6f9] dark:bg-[#15171b] px-3 py-1 flex items-center ${
                showBanReasonLine ? 'min-h-[68px]' : 'min-h-[50px]'
            }`}
        >
            <h3 className="sr-only">{t('room.chat.inputLabel')}</h3>
            <div
                className={`relative flex-1 min-w-0 h-full flex flex-col justify-center ${
                    showBanReasonLine ? 'min-h-[58px]' : 'min-h-[46px]'
                }`}
            >
                <div
                    ref={writeAreaRef}
                    contentEditable={!isDisabled}
                    suppressContentEditableWarning
                    onInput={handleInput}
                    onKeyDown={handleKeyDown}
                    onPaste={handlePaste}
                    className={`absolute left-0 w-full max-h-full py-[5px] overflow-y-auto hide-scrollbar text-sm leading-[1.4] outline-none ${showBanReasonLine ? 'top-2' : 'top-1/2 -translate-y-1/2'} ${isDisabled
                        ? 'text-gray-400 dark:text-gray-500 cursor-not-allowed'
                        : 'text-black dark:text-gray-100 cursor-text'
                        }`}
                />
                {showMentionDropdown && filteredMentionUsers.length > 0 && !isDisabled && (
                    <div ref={mentionDropdownRef}>
                        <MentionDropdown
                            users={filteredMentionUsers}
                            selectedIndex={mentionIndex}
                            onSelect={insertMention}
                            position={mentionPosition}
                            isMobile={isMobile}
                        />
                    </div>
                )}
                {(!hasContent() || isBanned || (chatDisabled && !isSuperAdmin)) && (
                    <span
                        className={`absolute left-0 py-[5px] text-sm leading-[1.4] pointer-events-none max-w-full pr-1 ${showBanReasonLine ? 'top-1 flex flex-col gap-0.5' : 'top-1/2 -translate-y-1/2'} ${isBanned
                            ? 'text-red-500 dark:text-red-400'
                            : (chatDisabled && !isSuperAdmin)
                                ? 'text-gray-500 dark:text-gray-400'
                                : 'text-[#757b8a] dark:text-gray-400'
                            }`}
                    >
                        <span className="block">{banMessage}</span>
                        {showBanReasonLine ? (
                            <span className="block text-xs font-normal text-red-500 dark:text-red-400 line-clamp-3 break-words">
                                {t('room.ban.inputReason', { reason: banReason })}
                            </span>
                        ) : null}
                    </span>
                )}
            </div>

            <button
                data-emoji-trigger="1"
                ref={emojiBtnRef}
                type="button"
                onClick={onEmojiToggle}
                tip={emojiTip}
                disabled={isDisabled}
                className={`${tipClassName} ml-2 w-8 h-8 rounded-lg inline-flex items-center justify-center transition-colors ${isDisabled
                    ? 'opacity-50 cursor-not-allowed'
                    : 'hover:bg-[rgba(145,150,161,0.1)] active:bg-[rgba(23,25,28,0.3)]'
                    }`}
                aria-label={t('room.chat.emojiButton')}
            >
                <FiSmile
                    className={`w-5 h-5 ${isDisabled ? 'text-gray-400 dark:text-gray-500' : 'text-[#525661] dark:text-gray-200'}`}
                    aria-hidden="true"
                />
            </button>
            <button
                type="button"
                onClick={onSend}
                disabled={isDisabled || !hasContent()}
                className={`ml-2 w-8 h-8 rounded-lg inline-flex items-center justify-center transition-colors ${isDisabled || !hasContent()
                        ? 'opacity-50 cursor-not-allowed'
                        : 'hover:bg-[rgba(145,150,161,0.1)] active:bg-[rgba(23,25,28,0.3)]'
                        }`}
                aria-label={t('room.chat.send')}
                title={t('room.chat.send')}
            >
                <FiSend className={`w-5 h-5 ${isDisabled || !hasContent() ? 'text-gray-400 dark:text-gray-500' : 'text-[#0182ff]'}`} />
            </button>
        </div>
    )
}

