import React, { useState } from 'react';
import ReactMarkdown from 'react-markdown';
import remarkGfm from 'remark-gfm';
import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter';
import { oneDark } from 'react-syntax-highlighter/dist/esm/styles/prism';
import {
    EmojieIcon,
    EditIcon,
    ReplyIcon,
    MoreIcon,
    DeleteIcon,
    PinIcon,
} from '../assets/icons';
import { getEmojiUrl, AllEmojis } from '../assets/emojis';
import Tooltip from './Tooltip';
import Avatar from './Avatar';
import ColoredIcon from './ColoredIcon';
import { usePlatform } from '../platform';

const fireIcon = getEmojiUrl('nature', 'fire');
const heartIcon = getEmojiUrl('symbols', 'heart');
const thumbsupIcon = getEmojiUrl('people', 'thumbsup');

const ICON_COLOR_DEFAULT = 'hsl(240, 4.294%, 68.039%)';
const USER_COLORS = ['#5865F2', '#EBA7CD', '#57F287', '#FEE75C', '#EB459E', '#ED4245'];

export const getUserColor = (name) => {
    let hash = 0;
    for (let i = 0; i < name.length; i++) { hash = name.charCodeAt(i) + ((hash << 5) - hash); }
    return USER_COLORS[Math.abs(hash) % USER_COLORS.length];
};

export const extractUrls = (text) => {
    const urlRegex = /(https?:\/\/[^\s]+)/g;
    return text.match(urlRegex) || [];
};

export const formatMentions = (text, roles) => {
    if (!text) return '';
    // First pass: replace @role:Name with role mention links
    let result = text.replace(/@role:([^\s]+)/g, (match, name) => {
        const role = roles?.find(r => r.name === name);
        const color = role?.color || '#99aab5';
        const displayName = name.startsWith('@') ? name : `@${name}`;
        return `[${displayName}](rolemention://${encodeURIComponent(name)}?color=${encodeURIComponent(color)})`;
    });
    // Second pass: replace @-prefixed role names (like @everyone) directly
    if (roles) {
        for (const role of roles) {
            if (role.name.startsWith('@')) {
                const escaped = role.name.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
                const re = new RegExp(`(?<!\\[)${escaped}\\b`, 'g');
                const color = role.color || '#99aab5';
                result = result.replace(re, `[${role.name}](rolemention://${encodeURIComponent(role.name)}?color=${encodeURIComponent(color)})`);
            }
        }
    }
    // Third pass: replace @username with user mention links (skip already-linked @)
    result = result.replace(/(?<!\[)@(\w+)/g, '[@$1](mention://$1)');
    return result;
};

export const formatEmojis = (text, customEmojis = []) => {
    if (!text) return '';
    return text.replace(/:([a-zA-Z0-9_]+):/g, (match, name) => {
        const custom = customEmojis.find(e => e.name === name);
        if (custom) return `![${match}](${custom.src})`;
        const emoji = AllEmojis.find(e => e.name === name);
        return emoji ? `![${match}](${emoji.src})` : match;
    });
};

export const parseAttachment = (content) => {
    if (!content || !content.startsWith('{')) return null;
    try {
        const parsed = JSON.parse(content);
        return parsed.type === 'attachment' ? parsed : null;
    } catch (e) {
        return null;
    }
};

export const parseSystemMessage = (content) => {
    if (!content || !content.startsWith('{')) return null;
    try {
        const parsed = JSON.parse(content);
        return parsed.type === 'system' ? parsed : null;
    } catch (e) {
        return null;
    }
};

const VIDEO_EXT_RE = /\.(mp4|webm|ogg|mov)(\?[^\s]*)?$/i;
const isVideoUrl = (url) => VIDEO_EXT_RE.test(url);

const getReactionIcon = (name, customEmojis = []) => {
    const custom = customEmojis.find(e => e.name === name);
    if (custom) return custom.src;
    switch (name) {
        case 'thumbsup': return thumbsupIcon;
        case 'heart': return heartIcon;
        case 'fire': return fireIcon;
        default: {
            const builtin = AllEmojis.find(e => e.name === name);
            return builtin ? builtin.src : heartIcon;
        }
    }
};

const isNewDay = (current, previous) => {
    if (!previous) return true;
    return current.getDate() !== previous.getDate()
        || current.getMonth() !== previous.getMonth()
        || current.getFullYear() !== previous.getFullYear();
};

const createMarkdownComponents = (openExternal) => ({
    a: ({ node, ...props }) => {
        if (props.href && props.href.startsWith('rolemention://')) {
            try {
                const url = new URL(props.href);
                const color = url.searchParams.get('color') || '#99aab5';
                return <span style={{ background: `${color}26`, borderRadius: '3px', color, fontWeight: 500, padding: '0 2px', cursor: 'default' }} title={props.children}>{props.children}</span>;
            } catch {
                return <span>{props.children}</span>;
            }
        }
        if (props.href && props.href.startsWith('mention://')) return <span style={{ background: 'hsla(234.935, 85.556%, 64.706%, 0.239)', borderRadius: '3px', color: 'hsl(228.14, 100%, 83.137%)', fontWeight: 500, padding: '0 2px', cursor: 'default' }} title={props.children}>{props.children}</span>;
        return <a {...props} onClick={(e) => { e.preventDefault(); openExternal(props.href); }} style={{ color: '#00b0f4', cursor: 'pointer', textDecoration: 'none' }} onMouseOver={(e) => e.target.style.textDecoration = 'underline'} onMouseOut={(e) => e.target.style.textDecoration = 'none'} />;
    },
    code({ node, inline, className, children, ...props }) {
        const match = /language-(\w+)/.exec(className || '');
        return !inline && match ? <SyntaxHighlighter style={oneDark} language={match[1]} PreTag="div" {...props}>{String(children).replace(/\n$/, '')}</SyntaxHighlighter> : <code className={className} {...props}>{children}</code>;
    },
    p: ({ node, ...props }) => <p style={{ margin: '0 0 6px 0' }} {...props} />,
    h1: ({ node, ...props }) => <h1 style={{ fontSize: '1.5rem', fontWeight: 700, margin: '12px 0 6px 0', lineHeight: 1.1 }} {...props} />,
    h2: ({ node, ...props }) => <h2 style={{ fontSize: '1.25rem', fontWeight: 700, margin: '10px 0 6px 0', lineHeight: 1.1 }} {...props} />,
    h3: ({ node, ...props }) => <h3 style={{ fontSize: '1.1rem', fontWeight: 700, margin: '8px 0 6px 0', lineHeight: 1.1 }} {...props} />,
    ul: ({ node, ...props }) => <ul style={{ margin: '0 0 6px 0', paddingLeft: '20px' }} {...props} />,
    ol: ({ node, ...props }) => <ol style={{ margin: '0 0 6px 0', paddingLeft: '20px' }} {...props} />,
    li: ({ node, ...props }) => <li style={{ margin: '0' }} {...props} />,
    hr: ({ node, ...props }) => <hr style={{ border: 'none', borderTop: '1px solid #4f545c', margin: '12px 0' }} {...props} />,
    img: ({ node, alt, src, ...props }) => {
        if (alt && alt.startsWith(':') && alt.endsWith(':')) {
            return <img src={src} alt={alt} style={{ width: '48px', height: '48px', verticalAlign: 'bottom', margin: '0 1px', display: 'inline' }} />;
        }
        return <img alt={alt} src={src} {...props} />;
    },
});

const IconButton = ({ onClick, emoji }) => (
    <div onClick={(e) => { e.stopPropagation(); onClick(e); }} className="icon-button" style={{ cursor: 'pointer', padding: '6px', fontSize: '16px', lineHeight: 1, color: 'var(--header-secondary)', transition: 'background-color 0.1s' }}>
        {emoji}
    </div>
);

const MessageToolbar = ({ onAddReaction, onEdit, onReply, onMore, isOwner, isAttachment }) => (
    <div className="message-toolbar">
        <Tooltip text="Thumbs Up" position="top">
            <IconButton onClick={() => onAddReaction('thumbsup')} emoji={<ColoredIcon src={thumbsupIcon} size="20px" />} />
        </Tooltip>
        <Tooltip text="Heart" position="top">
            <IconButton onClick={() => onAddReaction('heart')} emoji={<ColoredIcon src={heartIcon} size="20px" />} />
        </Tooltip>
        <Tooltip text="Fire" position="top">
            <IconButton onClick={() => onAddReaction('fire')} emoji={<ColoredIcon src={fireIcon} size="20px" />} />
        </Tooltip>
        <div style={{ width: '1px', height: '24px', margin: '2px 4px', backgroundColor: 'hsla(240, 4%, 60.784%, 0.122)' }}></div>
        <Tooltip text="Add Reaction" position="top">
            <IconButton onClick={() => onAddReaction(null)} emoji={<ColoredIcon src={EmojieIcon} color={ICON_COLOR_DEFAULT} size="20px" />} />
        </Tooltip>
        {isOwner && !isAttachment && (
            <Tooltip text="Edit" position="top">
                <IconButton onClick={onEdit} emoji={<ColoredIcon src={EditIcon} color={ICON_COLOR_DEFAULT} size="20px" />} />
            </Tooltip>
        )}
        <Tooltip text="Reply" position="top">
            <IconButton onClick={onReply} emoji={<ColoredIcon src={ReplyIcon} color={ICON_COLOR_DEFAULT} size="20px" />} />
        </Tooltip>
        <Tooltip text="More" position="top">
            <IconButton onClick={onMore} emoji={<ColoredIcon src={MoreIcon} color={ICON_COLOR_DEFAULT} size="20px" />} />
        </Tooltip>
    </div>
);

const MessageItem = React.memo(({
    msg,
    isGrouped,
    showDateDivider,
    showUnreadDivider,
    dateLabel,
    isMentioned,
    isOwner,
    isEditing,
    isHovered,
    editInput,
    username,
    roles,
    customEmojis,
    onHover,
    onLeave,
    onContextMenu,
    onAddReaction,
    onEdit,
    onReply,
    onMore,
    onEditInputChange,
    onEditKeyDown,
    onEditSave,
    onEditCancel,
    onReactionClick,
    onScrollToMessage,
    onProfilePopup,
    onImageClick,
    onLongPress,
    scrollToBottom,
    Attachment,
    LinkPreview,
    DirectVideo,
}) => {
    const { links } = usePlatform();
    const markdownComponents = createMarkdownComponents(links.openExternal);
    const currentDate = new Date(msg.created_at);
    const userColor = getUserColor(msg.username || 'Unknown');

    const systemMsg = parseSystemMessage(msg.content);

    const renderMessageContent = () => {
        if (systemMsg) return null;

        const attachmentMetadata = parseAttachment(msg.content);
        if (attachmentMetadata) {
            return <Attachment metadata={attachmentMetadata} onLoad={scrollToBottom} onImageClick={onImageClick} />;
        }

        const urls = extractUrls(msg.content);
        const isOnlyUrl = urls.length === 1 && msg.content.trim() === urls[0];
        const isGif = isOnlyUrl && (urls[0].includes('tenor.com') || urls[0].includes('giphy.com') || urls[0].endsWith('.gif'));
        const isDirectVideo = isOnlyUrl && isVideoUrl(urls[0]);

        return (
            <>
                {!isGif && !isDirectVideo && (
                    <ReactMarkdown remarkPlugins={[remarkGfm]} urlTransform={(url) => url} components={markdownComponents}>
                        {formatEmojis(formatMentions(msg.content, roles), customEmojis)}
                    </ReactMarkdown>
                )}
                {isDirectVideo && <DirectVideo src={urls[0]} marginTop={4} />}
                {urls.filter(u => !(isDirectVideo && u === urls[0])).map((url, i) => (
                    <LinkPreview key={i} url={url} />
                ))}
            </>
        );
    };

    const renderReactions = () => {
        if (!msg.reactions || Object.keys(msg.reactions).length === 0) return null;
        return (
            <div style={{ display: 'flex', gap: '4px', marginTop: '4px', flexWrap: 'wrap' }}>
                {Object.entries(msg.reactions).map(([emojiName, data]) => (
                    <div key={emojiName} onClick={() => onReactionClick(msg.id, emojiName, data.me)} style={{ display: 'flex', alignItems: 'center', backgroundColor: data.me ? 'rgba(88, 101, 242, 0.15)' : 'hsla(240, 4%, 60.784%, 0.078)', border: data.me ? '1px solid var(--brand-experiment)' : '1px solid transparent', borderRadius: '8px', padding: '2px 6px', cursor: 'pointer', gap: '4px' }}>
                        <ColoredIcon src={getReactionIcon(emojiName, customEmojis)} size="16px" color={null} />
                        <span style={{ fontSize: '12px', color: data.me ? '#dee0fc' : 'var(--header-secondary)', fontWeight: 600 }}>{data.count}</span>
                    </div>
                ))}
            </div>
        );
    };

    return (
        <React.Fragment>
            {showUnreadDivider && (
                <div className="unread-divider" role="separator">
                    <span className="unread-pill">
                        <svg className="unread-pill-cap" width="8" height="13" viewBox="0 0 8 13">
                            <path stroke="currentColor" fill="transparent" d="M8.16639 0.5H9C10.933 0.5 12.5 2.067 12.5 4V9C12.5 10.933 10.933 12.5 9 12.5H8.16639C7.23921 12.5 6.34992 12.1321 5.69373 11.4771L0.707739 6.5L5.69373 1.52292C6.34992 0.86789 7.23921 0.5 8.16639 0.5Z" />
                        </svg>
                        NEW
                    </span>
                </div>
            )}
            {showDateDivider && <div className="date-divider"><span>{dateLabel}</span></div>}
            {systemMsg ? (
                <div id={`msg-${msg.id}`} className="system-message-row">
                    <svg width="18" height="18" viewBox="0 0 24 24" fill="#23a559" style={{ flexShrink: 0 }}>
                        <path d="M2 7.4A5.4 5.4 0 0 1 7.4 2c.36 0 .7.22.83.55l1.93 4.64a1 1 0 0 1-.43 1.25L7 10a8.52 8.52 0 0 0 7 7l1.12-2.24a1 1 0 0 1 1.19-.51l5.06 1.56c.38.11.63.46.63.85C22 19.6 19.6 22 16.66 22h-.37C8.39 22 2 15.6 2 7.71V7.4ZM13 3a1 1 0 0 1 1-1 8 8 0 0 1 8 8 1 1 0 1 1-2 0 6 6 0 0 0-6-6 1 1 0 0 1-1-1Z"/>
                        <path d="M13 7a1 1 0 0 1 1-1 4 4 0 0 1 4 4 1 1 0 1 1-2 0 2 2 0 0 0-2-2 1 1 0 0 1-1-1Z"/>
                    </svg>
                    <span className="system-message-text">
                        {systemMsg.text || 'System event'}
                    </span>
                    <span className="system-message-time">
                        {currentDate.toLocaleTimeString([], { hour: 'numeric', minute: '2-digit' })}
                    </span>
                </div>
            ) : (
            <div
                id={`msg-${msg.id}`}
                className={`message-item${isGrouped ? ' message-grouped' : ''}`}
                style={isMentioned ? { background: 'hsla(36.894, 100%, 31.569%, 0.078)', position: 'relative' } : { position: 'relative' }}
                onMouseEnter={onHover}
                onMouseLeave={onLeave}
                onContextMenu={onContextMenu}
                onTouchStart={onLongPress?.onTouchStart}
                onTouchMove={onLongPress?.onTouchMove}
                onTouchEnd={onLongPress?.onTouchEnd}
            >
                {isMentioned && <div style={{ background: 'hsl(34, 50.847%, 53.725%)', bottom: 0, display: 'block', left: 0, pointerEvents: 'none', position: 'absolute', top: 0, width: '2px' }} />}

                {msg.replyToId && msg.replyToUsername && (
                    <div className="message-reply-context" onClick={() => onScrollToMessage(msg.replyToId)}>
                        <div className="reply-spine" />
                        <Avatar username={msg.replyToUsername} avatarUrl={msg.replyToAvatarUrl} size={16} className="reply-avatar" />
                        <span className="reply-author" style={{ color: getUserColor(msg.replyToUsername) }}>
                            @{msg.replyToDisplayName || msg.replyToUsername}
                        </span>
                        <span className="reply-text">{msg.decryptedReply || '[Encrypted]'}</span>
                    </div>
                )}

                {isGrouped ? (
                    <div className="message-avatar-wrapper">
                    </div>
                ) : (
                    <div className="message-avatar-wrapper">
                        <Avatar
                            username={msg.username}
                            avatarUrl={msg.avatarUrl}
                            size={40}
                            className="message-avatar"
                            style={{ cursor: 'pointer' }}
                            onClick={(e) => onProfilePopup(e, msg)}
                        />
                    </div>
                )}
                <div className="message-body">
                    {!isGrouped && (
                        <div className="message-header">
                            <span
                                className="username"
                                style={{ color: userColor, cursor: 'pointer' }}
                                onClick={(e) => onProfilePopup(e, msg)}
                            >
                                {msg.displayName || msg.username || 'Unknown'}
                            </span>
                            {msg.isVerified === false && <span className="verification-failed" title="Signature Verification Failed!"><svg aria-hidden="true" role="img" width="16" height="16" viewBox="0 0 24 24" fill="var(--danger)"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-2h2v2zm0-4h-2V7h2v6z"></path></svg></span>}
                            <span className="timestamp">{currentDate.toLocaleTimeString([], { hour: 'numeric', minute: '2-digit' })}</span>
                        </div>
                    )}
                    <div style={{ position: 'relative' }}>
                        {isEditing ? (
                            <div className="message-editing">
                                <textarea
                                    className="message-edit-textarea"
                                    value={editInput}
                                    onChange={onEditInputChange}
                                    onKeyDown={onEditKeyDown}
                                    autoFocus
                                />
                                <div className="message-edit-hint">
                                    escape to <span onClick={onEditCancel}>cancel</span> · enter to <span onClick={onEditSave}>save</span>
                                </div>
                            </div>
                        ) : (
                            <div className="message-content">
                                {renderMessageContent()}
                                {msg.editedAt && <span className="edited-indicator">(edited)</span>}
                                {renderReactions()}
                            </div>
                        )}
                        {isHovered && !isEditing && (
                            <MessageToolbar isOwner={isOwner}
                                isAttachment={!!parseAttachment(msg.content)}
                                onAddReaction={onAddReaction}
                                onEdit={onEdit}
                                onReply={onReply}
                                onMore={onMore}
                            />
                        )}
                    </div>
                </div>
            </div>
            )}
        </React.Fragment>
    );
}, (prevProps, nextProps) => {
    return (
        prevProps.msg.id === nextProps.msg.id &&
        prevProps.msg.content === nextProps.msg.content &&
        prevProps.msg.editedAt === nextProps.msg.editedAt &&
        prevProps.msg.reactions === nextProps.msg.reactions &&
        prevProps.msg.decryptedReply === nextProps.msg.decryptedReply &&
        prevProps.msg.isVerified === nextProps.msg.isVerified &&
        prevProps.isHovered === nextProps.isHovered &&
        prevProps.isEditing === nextProps.isEditing &&
        prevProps.editInput === nextProps.editInput &&
        prevProps.isGrouped === nextProps.isGrouped &&
        prevProps.showDateDivider === nextProps.showDateDivider &&
        prevProps.showUnreadDivider === nextProps.showUnreadDivider &&
        prevProps.isMentioned === nextProps.isMentioned &&
        prevProps.roles === nextProps.roles &&
        prevProps.customEmojis === nextProps.customEmojis
    );
});

MessageItem.displayName = 'MessageItem';

export default MessageItem;
