'use client';

import React, { useRef, useEffect, useState, useCallback, useMemo } from 'react';
import { createPortal } from 'react-dom';
import type { InputAsset } from '../../types/node';
import { cn } from '@/utils';
import { Music, UserCircle } from 'lucide-react';
import { SecureImage } from '@/components/common/SecureImage';
import { SecureVideo } from '../../nodes/components/SecureVideo';
import {
    createMentionChipElement,
    filterMentionCandidates,
    parseMentionTokens,
} from './mentionUtils';

interface AutoResizeTextareaProps {
    value: string;
    onChange: (v: string) => void;
    onEnter: () => void;
    isExpanded?: boolean;
    placeholder?: string;
    /** 可 @ 的素材列表，用于在输入时弹出候选 */
    inputAssets?: InputAsset[];
}

export const AutoResizeTextarea = ({ 
    value, 
    onChange, 
    onEnter,
    isExpanded,
    placeholder,
    inputAssets
}: AutoResizeTextareaProps) => {
    const editorRef = useRef<HTMLDivElement>(null);
    const [mentionOpen, setMentionOpen] = useState(false);
    const [mentionQuery, setMentionQuery] = useState('');
    const [mentionStart, setMentionStart] = useState<number | null>(null);
    const [mentionPosition, setMentionPosition] = useState<{ top: number; left: number; width: number } | null>(null);
    const isComposingRef = useRef(false);
    
    const closeMention = useCallback(() => {
        setMentionOpen(false);
        setMentionQuery('');
        setMentionStart(null);
        setMentionPosition(null);
    }, []);

    // Focus when expanded
    useEffect(() => {
        if (isExpanded && editorRef.current) {
            requestAnimationFrame(() => {
                editorRef.current?.focus();
                // Move cursor to end
                const selection = window.getSelection();
                if (selection && editorRef.current) {
                    const range = document.createRange();
                    range.selectNodeContents(editorRef.current);
                    range.collapse(false);
                    selection.removeAllRanges();
                    selection.addRange(range);
                }
            });
        }
    }, [isExpanded]);

    // 从 DOM 读取纯文本内容（chip span 的 data-mention-text 就是 @图片1）
    const getTextFromDOM = useCallback((): string => {
        if (!editorRef.current) return '';
        
        let text = '';
        const walk = (node: Node) => {
            if (node.nodeType === Node.TEXT_NODE) {
                text += node.textContent || '';
            } else if (node.nodeType === Node.ELEMENT_NODE) {
                const el = node as HTMLElement;
                if (el.classList.contains('mention-chip')) {
                    // chip span 的 data-mention-text 就是 @图片1
                    text += el.getAttribute('data-mention-text') || '';
                } else if (el.tagName === 'BR') {
                    text += '\n';
                } else {
                    node.childNodes.forEach(walk);
                }
            }
        };
        editorRef.current.childNodes.forEach(walk);
        return text;
    }, []);

    // 光标偏移与恢复（纯 DOM 工具，稳定引用）
    const getCursorOffset = useCallback((editor: HTMLElement, range: Range): number => {
        let offset = 0;
        const walk = (node: Node): boolean => {
            if (node === range.startContainer) {
                offset += range.startOffset;
                return true;
            }
            if (node.nodeType === Node.TEXT_NODE) {
                offset += (node.textContent || '').length;
            } else if (node.nodeType === Node.ELEMENT_NODE) {
                const el = node as HTMLElement;
                if (el.classList.contains('mention-chip')) {
                    offset += (el.getAttribute('data-mention-text') || el.innerText || '').length;
                } else {
                    for (let i = 0; i < node.childNodes.length; i++) {
                        if (walk(node.childNodes[i])) return true;
                    }
                }
            }
            return false;
        };
        for (let i = 0; i < editor.childNodes.length; i++) {
            if (walk(editor.childNodes[i])) break;
        }
        return offset;
    }, []);

    const restoreCursor = useCallback((editor: HTMLElement, offset: number) => {
        let currentOffset = 0;
        let found = false;
        const walk = (node: Node): boolean => {
            if (node.nodeType === Node.TEXT_NODE) {
                const len = (node.textContent || '').length;
                if (currentOffset + len >= offset) {
                    const range = document.createRange();
                    range.setStart(node, Math.min(offset - currentOffset, len));
                    range.collapse(true);
                    const selection = window.getSelection();
                    if (selection) {
                        selection.removeAllRanges();
                        selection.addRange(range);
                    }
                    return true;
                }
                currentOffset += len;
            } else if (node.nodeType === Node.ELEMENT_NODE) {
                const el = node as HTMLElement;
                if (el.classList.contains('mention-chip')) {
                    const len = (el.getAttribute('data-mention-text') || el.innerText || '').length;
                    if (currentOffset + len >= offset) {
                        const range = document.createRange();
                        range.setStartAfter(el);
                        range.collapse(true);
                        const selection = window.getSelection();
                        if (selection) {
                            selection.removeAllRanges();
                            selection.addRange(range);
                        }
                        return true;
                    }
                    currentOffset += len;
                } else {
                    for (let i = 0; i < node.childNodes.length; i++) {
                        if (walk(node.childNodes[i])) return true;
                    }
                }
            }
            return false;
        };
        for (let i = 0; i < editor.childNodes.length; i++) {
            if (walk(editor.childNodes[i])) {
                found = true;
                break;
            }
        }
        if (!found) {
            const range = document.createRange();
            range.selectNodeContents(editor);
            range.collapse(false);
            const selection = window.getSelection();
            if (selection) {
                selection.removeAllRanges();
                selection.addRange(range);
            }
        }
    }, []);

    // 根据纯文本 value 渲染 DOM（文本节点 + chip span）
    // 只在外部 value 变化时调用，用户输入时不调用
    const renderContent = useCallback((newValue: string, preserveCursor: boolean = true) => {
        if (!editorRef.current) return;
        
        const editor = editorRef.current;
        
        // 保存当前光标位置
        const selection = window.getSelection();
        let cursorOffset = 0;
        if (preserveCursor && selection && selection.rangeCount > 0) {
            const range = selection.getRangeAt(0);
            cursorOffset = getCursorOffset(editor, range);
        }
        
        // 清空并重新渲染
        editor.innerHTML = '';
        
        if (!newValue) {
            if (preserveCursor) {
                // 确保光标在编辑器内
                editor.focus();
            }
            return;
        }
        
        // 解析 value，切分为文本段和 @别名段
        const tokens = parseMentionTokens(newValue, inputAssets);
        
        tokens.forEach(token => {
            if (token.type === 'text') {
                editor.appendChild(document.createTextNode(token.text));
            } else {
                const chip = createMentionChipElement(token.asset, isExpanded);
                editor.appendChild(chip);
            }
        });
        
        // 恢复光标位置
        if (preserveCursor) {
            restoreCursor(editor, cursorOffset);
        }
    }, [inputAssets, isExpanded, getCursorOffset, restoreCursor]);

    // 初始渲染和外部 value 变化时渲染
    const prevValueRef = useRef<string>(value);
    const isUserInputRef = useRef<boolean>(false);
    
    useEffect(() => {
        // 只在外部 value 变化时重新渲染（不是用户输入导致的变化）
        if (isUserInputRef.current) {
            // 用户输入导致的变化，不重新渲染
            isUserInputRef.current = false;
            prevValueRef.current = value;
            return;
        }
        
        const currentText = getTextFromDOM();
        if (value !== prevValueRef.current && value !== currentText) {
            renderContent(value, false);
            prevValueRef.current = value;
        }
    }, [value, getTextFromDOM, renderContent]);

    // 更新候选浮层位置
    const updateMentionPosition = useCallback(() => {
        const selection = window.getSelection();
        if (!selection || selection.rangeCount === 0) return;
        
        const range = selection.getRangeAt(0);
        const rect = range.getBoundingClientRect();
        
        setMentionPosition({
            left: rect.left,
            top: rect.top,
            width: 200,
        });
    }, []);

    // 处理输入
    const handleInput = useCallback(() => {
        if (isComposingRef.current) return;
        
        const text = getTextFromDOM();
        
        // 标记这是用户输入
        isUserInputRef.current = true;
        onChange(text);
        
        // 检查是否输入了 @
        const selection = window.getSelection();
        if (!selection || selection.rangeCount === 0) return;
        
        const range = selection.getRangeAt(0);
        const editor = editorRef.current;
        if (!editor) return;
        
        const cursorOffset = getCursorOffset(editor, range);
        const charBefore = text[cursorOffset - 1];
        
        if (charBefore === '@') {
            setMentionOpen(true);
            setMentionQuery('');
            setMentionStart(cursorOffset - 1);
            updateMentionPosition();
            return;
        }
        
        if (mentionOpen && mentionStart !== null) {
            const query = text.slice(mentionStart + 1, cursorOffset);
            setMentionQuery(query);
            if (!query || /\s/.test(query)) {
                closeMention();
            } else {
                updateMentionPosition();
            }
        }
    }, [getTextFromDOM, onChange, mentionOpen, mentionStart, updateMentionPosition, closeMention, getCursorOffset]);

    // 处理键盘事件
    const handleKeyDown = useCallback((e: React.KeyboardEvent) => {
        const editor = editorRef.current;
        if (!editor) return;
        
        // 阻止 Backspace 和 Delete 键冒泡到画布层（避免删除画布节点）
        if (e.key === 'Backspace' || e.key === 'Delete') {
            e.stopPropagation();
        }
        
        // Enter 提交（折叠模式下不支持换行）
        if (e.key === 'Enter') {
            if (!isExpanded || !e.shiftKey) {
                e.preventDefault();
                onEnter();
                return;
            }
            // 展开模式下，Shift+Enter 允许换行（浏览器默认行为）
        }
        
        // Backspace 删除 chip
        if (e.key === 'Backspace' && !e.shiftKey && !e.altKey && !e.metaKey && !e.ctrlKey) {
            const selection = window.getSelection();
            if (!selection || selection.rangeCount === 0) return;
            
            const range = selection.getRangeAt(0);
            
            // 如果有选区，让浏览器默认处理
            if (!range.collapsed) return;
            
            // 检查光标前面是否是 chip
            const container = range.startContainer;
            const offset = range.startOffset;
            
            // 如果光标在文本节点开头，检查前一个兄弟节点
            if (container.nodeType === Node.TEXT_NODE && offset === 0) {
                const prevSibling = container.previousSibling;
                if (prevSibling && prevSibling.nodeType === Node.ELEMENT_NODE) {
                    const el = prevSibling as HTMLElement;
                    if (el.classList.contains('mention-chip')) {
                        e.preventDefault();
                        el.remove();
                        isUserInputRef.current = true;
                        const text = getTextFromDOM();
                        onChange(text);
                        return;
                    }
                }
            }
            
            // 如果光标在编辑器开头，检查第一个子节点
            if (container === editor && offset === 0) {
                const firstChild = editor.firstChild;
                if (firstChild && firstChild.nodeType === Node.ELEMENT_NODE) {
                    const el = firstChild as HTMLElement;
                    if (el.classList.contains('mention-chip')) {
                        e.preventDefault();
                        el.remove();
                        isUserInputRef.current = true;
                        const text = getTextFromDOM();
                        onChange(text);
                        return;
                    }
                }
            }
            
            // 如果光标在元素节点内，检查前一个子节点
            if (container.nodeType === Node.ELEMENT_NODE && offset > 0) {
                const prevChild = container.childNodes[offset - 1];
                if (prevChild && prevChild.nodeType === Node.ELEMENT_NODE) {
                    const el = prevChild as HTMLElement;
                    if (el.classList.contains('mention-chip')) {
                        e.preventDefault();
                        el.remove();
                        isUserInputRef.current = true;
                        const text = getTextFromDOM();
                        onChange(text);
                        return;
                    }
                }
            }
        }
    }, [getTextFromDOM, onChange, onEnter, isExpanded]);

    // 候选列表
    const candidates = useMemo(() => {
        return filterMentionCandidates(inputAssets, mentionQuery);
    }, [inputAssets, mentionQuery]);

    // 插入 mention
    const applyMention = useCallback((asset: InputAsset) => {
        if (mentionStart === null || !editorRef.current) return;
        
        const editor = editorRef.current;
        const text = getTextFromDOM();
        const alias = asset.mentionAlias || asset.label || asset.id;
        
        // 获取当前光标位置
        const selection = window.getSelection();
        if (!selection || selection.rangeCount === 0) return;
        
        const range = selection.getRangeAt(0);
        const cursorOffset = getCursorOffset(editor, range);
        
        // 构建新文本：删除 @ 和查询，插入 @别名 + 空格
        const before = text.slice(0, mentionStart);
        const after = text.slice(cursorOffset);
        const inserted = `@${alias} `;
        const newText = before + inserted + after;
        
        // 标记为用户输入，但需要重新渲染（因为要插入 chip）
        isUserInputRef.current = false; // 这次需要重新渲染
        onChange(newText);
        closeMention();
        
        // 光标移到插入内容后面
        const newCursorOffset = before.length + inserted.length;
        requestAnimationFrame(() => {
            renderContent(newText, false);
            requestAnimationFrame(() => {
                restoreCursor(editor, newCursorOffset);
                editor.focus();
            });
        });
    }, [mentionStart, getTextFromDOM, onChange, closeMention, getCursorOffset, restoreCursor, renderContent]);

    return (
        <div className="relative w-full h-full flex items-center">
            {/* contentEditable 编辑器 */}
            <div
                ref={editorRef}
                contentEditable
                onInput={handleInput}
                onKeyDown={handleKeyDown}
                onClick={(e) => {
                    // 确保点击时聚焦
                    e.stopPropagation();
                    if (editorRef.current) {
                        editorRef.current.focus();
                        // 如果没有内容，将光标移到末尾
                        if (!editorRef.current.textContent) {
                            const range = document.createRange();
                            const sel = window.getSelection();
                            range.selectNodeContents(editorRef.current);
                            range.collapse(false);
                            sel?.removeAllRanges();
                            sel?.addRange(range);
                        }
                    }
                }}
                onCompositionStart={() => { isComposingRef.current = true; }}
                onCompositionEnd={() => { 
                    isComposingRef.current = false;
                    handleInput();
                }}
                onBlur={() => {
                    setTimeout(() => {
                        closeMention();
                    }, 150);
                }}
                data-placeholder={placeholder || (isExpanded ? "输入你的创意" : "有什么可以帮您？")}
                className={cn(
                    "w-full bg-transparent border-none outline-none text-foreground resize-none text-[13px] custom-scrollbar empty:before:content-[attr(data-placeholder)] empty:before:text-white/30 cursor-text",
                    isExpanded 
                        ? "px-2 min-h-[40px] leading-relaxed" 
                        : "px-0 leading-normal"
                )}
                style={isExpanded ? { 
                    maxHeight: '200px',
                    overflowY: 'auto',
                    wordWrap: 'break-word',
                    whiteSpace: 'pre-wrap'
                } : {
                    overflowY: 'hidden',
                    overflowX: 'auto',
                    whiteSpace: 'nowrap',
                    wordWrap: 'normal'
                }}
            />
            
            {/* 候选浮层 */}
            {mentionOpen && candidates.length > 0 && mentionPosition &&
                typeof window !== 'undefined' &&
                createPortal(
                    <div
                        className="fixed z-[9999] rounded-xl bg-black/85 border border-white/10 shadow-xl backdrop-blur-md text-xs text-foreground interaction-model-popover"
                        style={{
                            left: mentionPosition.left,
                            top: mentionPosition.top,
                            transform: 'translateY(-100%) translateY(-8px)',
                            maxWidth: 260,
                            minWidth: 200,
                        }}
                    >
                        {candidates.map(asset => {
                            const alias = asset.mentionAlias || asset.label || asset.id;
                            return (
                                <button
                                    key={asset.id}
                                    type="button"
                                    onMouseDown={(e) => {
                                        e.preventDefault();
                                        applyMention(asset);
                                    }}
                                    className="w-full text-left px-3 py-1.5 hover:bg-white/10 flex items-center gap-2"
                                >
                                    <div className={cn(
                                        'w-7 h-7 rounded-full overflow-hidden border border-white/15 flex items-center justify-center bg-black/40 shrink-0'
                                    )}>
                                        {asset.type === 'video' ? (
                                            <SecureVideo
                                                src={asset.src}
                                                className="w-full h-full object-cover"
                                                muted
                                                loop
                                                autoPlay
                                                playsInline
                                            />
                                        ) : asset.type === 'audio' ? (
                                            <div className={cn(
                                                'w-full h-full flex items-center justify-center',
                                                asset.gender ? 'bg-black/40' : 'bg-cyan-500/20'
                                            )}>
                                                {asset.gender ? (
                                                    <UserCircle
                                                        size={18}
                                                        className={cn(
                                                            asset.gender === '男' || asset.gender === 'male'
                                                                ? 'text-blue-400'
                                                                : 'text-pink-400'
                                                        )}
                                                    />
                                                ) : (
                                                    <Music className="w-4 h-4 text-cyan-400" />
                                                )}
                                            </div>
                                        ) : (
                                            <SecureImage
                                                src={asset.src}
                                                alt={alias}
                                                className="w-full h-full object-cover"
                                            />
                                        )}
                                    </div>
                                    <div className="flex flex-col min-w-0">
                                        <span className="truncate text-[12px]">{alias}</span>
                                        <span className="text-[10px] text-foreground/50">
                                            {asset.type === 'image' ? '图片素材' : asset.type === 'video' ? '视频素材' : '音频素材'}
                                        </span>
                                    </div>
                                </button>
                            );
                        })}
                    </div>,
                    document.body
                )
            }
        </div>
    );
};
