import { useCallback, useContext, useEffect, useMemo, useRef, useState } from "preact/hooks";
import { formatMessage, type IMessage } from "../messages";
import { GlobalContext } from "../context";

interface IProps {
    message: IMessage;
    index: number;
    isLastUser: boolean;
    isLastAssistant: boolean;
}

export const Message = ({ message, index, isLastUser, isLastAssistant }: IProps) => {
    const { editMessage, deleteMessage, setCurrentSwipe } = useContext(GlobalContext);
    const [editing, setEditing] = useState(false);
    const [savedMessage, setSavedMessage] = useState('');
    const textareaRef = useRef<HTMLTextAreaElement>(null);
    const textRef = useRef<HTMLDivElement>(null);

    const swipe = useMemo(() => message.swipes[message.currentSwipe], [message.swipes, message.currentSwipe]);
    const content = useMemo(() => swipe?.displayContent ?? swipe?.content, [swipe]);
    const htmlContent = useMemo(() => formatMessage(content ?? ''), [content]);

    const handleToggleEdit = useCallback(() => {
        setEditing(!editing);
        if (!editing) {
            setSavedMessage(content);
        }
    }, [editing, content]);

    const handleCancelEdit = useCallback(() => {
        setEditing(false);
        editMessage(index, savedMessage);
    }, [editMessage, index, savedMessage]);

    const handleDeleteMessage = useCallback(() => {
        if (confirm('Delete message?')) {
            setEditing(false);
            deleteMessage(index);
        }
    }, [deleteMessage, index]);

    const handleEdit = useCallback((e: InputEvent) => {
        if (e.target instanceof HTMLTextAreaElement) {
            const newContent = e.target.value;
            editMessage(index, newContent);
        }
    }, [editMessage, index]);

    const handleSwipeLeft = useCallback(() => {
        setCurrentSwipe(index, message.currentSwipe - 1);
        if (textRef.current) {
            textRef.current.style.animationName = '';
            textRef.current.style.animationName = 'swipe-from-left';
        }
    }, [setCurrentSwipe, index, message]);

    const handleSwipeRight = useCallback(() => {
        setCurrentSwipe(index, message.currentSwipe + 1);
        if (textRef.current) {
            textRef.current.style.animationName = '';
            textRef.current.style.animationName = 'swipe-from-right';
        }
    }, [setCurrentSwipe, index, message]);

    useEffect(() => {
        if (textareaRef.current) {
            const area = textareaRef.current;
            area.style.height = '0'; // reset
            area.style.height = `${area.scrollHeight + 10}px`;
        }
    }, [content, editing]);

    return (
        <div class={`message role-${message.role} ${isLastUser ? 'last-user' : ''}`}>
            <div class="content">
                {editing
                    ? <textarea onInput={handleEdit} value={content} class="edit-input" ref={textareaRef} />
                    : <div class="text" dangerouslySetInnerHTML={{ __html: htmlContent }} ref={textRef}/>
                }
                {(isLastUser || message.role === 'assistant') &&
                    <div class="buttons">
                        {editing
                            ? <>
                                <button class="icon" onClick={handleToggleEdit}>✔</button>
                                <button class="icon" onClick={handleDeleteMessage}>🗑️</button>
                                <button class="icon" onClick={handleCancelEdit}>❌</button>
                            </>
                            : <>
                                {isLastAssistant &&
                                    <div class="swipes">
                                        <div onClick={handleSwipeLeft}>◀</div>
                                        <div>{message.currentSwipe + 1}/{message.swipes.length}</div>
                                        <div onClick={handleSwipeRight}>▶</div>
                                    </div>
                                }
                                <button class="icon" onClick={handleToggleEdit}>🖊</button>
                            </>
                        }
                    </div>
                }
            </div>
        </div>
    );
};