/**
 * Chat Simulator Component
 * 
 * A full recreation of the chat window for preview purposes.
 * Uses CSS variables for dynamic theming based on PresetGlobalValues.
 * 
 * @since 1.5.0
 */

import React, { useState, useMemo } from 'react';
import { t } from '@/lib/i18n';
import { 
    PresetGlobalValues, 
    ElementSettings,
    FieldValue,
    createCustomValue,
    createGlobalRef,
    resolveFieldValue,
    DEFAULT_GLOBAL_VALUES,
    DEFAULT_ELEMENT_SETTINGS
} from '../../../types/appearance';
import { 
    Send, 
    Bot,
    User,
    RefreshCw
} from 'lucide-react';
import { HEADER_LUCIDE_ICON_MAP } from '../../common/LucideIconPicker';
import type { HeaderAvatarIconName } from '../../../types/appearance';
import { parseBorderRadiusShorthand, resolveBorderRadiusToShorthand } from '../../common/BorderRadiusFieldEditor';

// ============================================================
// Types
// ============================================================

export interface ChatMessage {
    id: string;
    type: 'user' | 'bot';
    content: string;
    timestamp?: Date;
    element?: React.ReactNode;
}

export interface ChatSimulatorProps {
    globalValues?: PresetGlobalValues;
    elementSettings?: ElementSettings;
    messages?: ChatMessage[];
    showTypingIndicator?: boolean;
    previewElement?: React.ReactNode;
    className?: string;
    scale?: number;
    onRefresh?: () => void;
    /** Text direction for the preview. Defaults to 'rtl'. */
    isRTL?: boolean;
    /** Language of the preset being previewed ('he' | 'en'). When set, overrides isRTL and demo text language. */
    presetLanguage?: string;
}

// ============================================================
// Default Messages
// ============================================================

function getDefaultMessages(lang?: string): ChatMessage[] {
    const isHebrew = lang === 'he';
    return [
        {
            id: '1',
            type: 'bot',
            content: lang
                ? (isHebrew
                    ? 'שלום! 👋 אני העוזר של BoostBot. איך אוכל לעזור לך היום?'
                    : 'Hello! 👋 I\'m the BoostBot assistant. How can I help you today?')
                : t('Hello! 👋 I\'m the BoostBot assistant. How can I help you today?'),
        },
        {
            id: '2',
            type: 'user',
            content: lang
                ? (isHebrew
                    ? 'היי! אשמח לשמוע עוד על המוצרים שלכם'
                    : 'Hi! I\'d like to learn more about your products')
                : t('Hi! I\'d like to learn more about your products'),
        },
        {
            id: '3',
            type: 'bot',
            content: lang
                ? (isHebrew
                    ? 'בטח! הנה כמה מהמוצרים הפופולריים שלנו:'
                    : 'Sure! Here are some of our popular products:')
                : t('Sure! Here are some of our popular products:'),
        },
    ];
}

// ============================================================
// Sub-Components
// ============================================================

interface HeaderProps {
    settings: ElementSettings['header'];
    globalValues: PresetGlobalValues;
}

const Header: React.FC<HeaderProps> = ({ settings, globalValues }) => {
    const bgColor = resolveFieldValue(settings.background, globalValues);
    const textColor = resolveFieldValue(settings.text, globalValues);
    const height = resolveFieldValue(settings.height, globalValues);
    const padding = resolveFieldValue(settings.padding, globalValues);
    const [isResetHovered, setIsResetHovered] = useState(false);
    const [isCloseHovered, setIsCloseHovered] = useState(false);
    const [isMinimizeHovered, setIsMinimizeHovered] = useState(false);
    
    // Get global typography for fallbacks
    const globalFontFamily = globalValues.typography?.fontFamily || 'inherit';
    const globalHeading = globalValues.typography?.heading;
    const globalBody = globalValues.typography?.body;
    
    // Get typography settings (with global values as fallbacks)
    const typography = settings.typography || {};
    const fontFamily = typography.fontFamily ? resolveFieldValue(typography.fontFamily, globalValues) : globalFontFamily;
    const fontSize = typography.fontSize ? resolveFieldValue(typography.fontSize, globalValues) : (globalHeading?.fontSize || '16px');
    const fontWeight = typography.fontWeight ? resolveFieldValue(typography.fontWeight, globalValues) : (globalHeading?.fontWeight || '600');
    const fontStyle = typography.fontStyle ? resolveFieldValue(typography.fontStyle, globalValues) : 'normal';
    const textTransform = typography.textTransform ? resolveFieldValue(typography.textTransform, globalValues) : 'none';
    const letterSpacing = typography.letterSpacing ? resolveFieldValue(typography.letterSpacing, globalValues) : 'normal';
    const textDecoration = typography.textDecoration ? resolveFieldValue(typography.textDecoration, globalValues) : 'none';
    const lineHeight = typography.lineHeight ? resolveFieldValue(typography.lineHeight, globalValues) : (globalHeading?.lineHeight || '1.4');
    const textShadow = typography.textShadow ? resolveFieldValue(typography.textShadow, globalValues) : 'none';

    // Subtitle typography (styles only)
    const subtitleTypography = settings.subtitleTypography || {};
    const subtitleFontFamily = subtitleTypography.fontFamily ? resolveFieldValue(subtitleTypography.fontFamily, globalValues) : globalFontFamily;
    const subtitleFontSize = subtitleTypography.fontSize ? resolveFieldValue(subtitleTypography.fontSize, globalValues) : (globalBody?.fontSize || '12px');
    const subtitleFontWeight = subtitleTypography.fontWeight ? resolveFieldValue(subtitleTypography.fontWeight, globalValues) : (globalBody?.fontWeight || '400');
    const subtitleLineHeight = subtitleTypography.lineHeight ? resolveFieldValue(subtitleTypography.lineHeight, globalValues) : (globalBody?.lineHeight || '1.2');
    const subtitleLetterSpacing = subtitleTypography.letterSpacing ? resolveFieldValue(subtitleTypography.letterSpacing, globalValues) : 'normal';
    const subtitleTextTransform = subtitleTypography.textTransform ? resolveFieldValue(subtitleTypography.textTransform, globalValues) : 'none';
    const subtitleFontStyle = subtitleTypography.fontStyle ? resolveFieldValue(subtitleTypography.fontStyle, globalValues) : 'normal';
    const subtitleTextDecoration = subtitleTypography.textDecoration ? resolveFieldValue(subtitleTypography.textDecoration, globalValues) : 'none';
    const subtitleTextShadow = subtitleTypography.textShadow ? resolveFieldValue(subtitleTypography.textShadow, globalValues) : 'none';

    // Header container border (complete border controls)
    const headerBorderRadiusResolved = (settings as unknown as { borderRadius?: FieldValue }).borderRadius
        ? resolveBorderRadiusToShorthand((settings as unknown as { borderRadius?: FieldValue }).borderRadius as FieldValue, globalValues, '16px')
        : resolveBorderRadiusToShorthand('16px', globalValues, '16px');
    const headerCorners = parseBorderRadiusShorthand(headerBorderRadiusResolved);
    const headerBorderStyle = (settings as unknown as { borderStyle?: 'none' | 'solid' | 'dashed' | 'dotted' }).borderStyle || 'none';
    const headerBorderWidthRaw = (settings as unknown as { borderWidth?: unknown }).borderWidth;
    const headerBorderWidth = (() => {
        if (headerBorderWidthRaw && typeof headerBorderWidthRaw === 'object') {
            const o = headerBorderWidthRaw as Record<string, unknown>;
            if (typeof o.top === 'string' && typeof o.right === 'string' && typeof o.bottom === 'string' && typeof o.left === 'string') {
                return { top: o.top, right: o.right, bottom: o.bottom, left: o.left };
            }
        }
        const resolved = headerBorderWidthRaw
            ? resolveFieldValue(headerBorderWidthRaw as FieldValue, globalValues)
            : '0px';
        return { top: resolved, right: resolved, bottom: resolved, left: resolved };
    })();
    const headerBorderColor = (settings as unknown as { borderColor?: FieldValue }).borderColor
        ? resolveFieldValue((settings as unknown as { borderColor?: FieldValue }).borderColor as FieldValue, globalValues)
        : 'transparent';

    // Avatar/Icon wrapper (styles only)
    const avatarSize = settings.avatarSize ? resolveFieldValue(settings.avatarSize, globalValues) : '40px';
    const avatarBackground = settings.avatarBackground ? resolveFieldValue(settings.avatarBackground, globalValues) : 'rgba(255,255,255,0.2)';
    const avatarBorderRadius = settings.avatarBorderRadius ? resolveFieldValue(settings.avatarBorderRadius, globalValues) : '9999px';
    const avatarBorderWidthRaw = (settings as unknown as { avatarBorderWidth?: unknown }).avatarBorderWidth;
    const avatarBorderWidth = (() => {
        if (avatarBorderWidthRaw && typeof avatarBorderWidthRaw === 'object') {
            const o = avatarBorderWidthRaw as Record<string, unknown>;
            if (typeof o.top === 'string' && typeof o.right === 'string' && typeof o.bottom === 'string' && typeof o.left === 'string') {
                return { top: o.top, right: o.right, bottom: o.bottom, left: o.left };
            }
        }
        const resolved = avatarBorderWidthRaw
            ? resolveFieldValue(avatarBorderWidthRaw as FieldValue, globalValues)
            : '2px';
        return { top: resolved, right: resolved, bottom: resolved, left: resolved };
    })();
    const avatarBorderColor = settings.avatarBorderColor ? resolveFieldValue(settings.avatarBorderColor, globalValues) : 'rgba(255,255,255,0.2)';
    const avatarIconColor = settings.avatarIconColor ? resolveFieldValue(settings.avatarIconColor, globalValues) : textColor;
    const statusIndicatorSize = resolveFieldValue(
        (settings as any).statusIndicatorSize || createCustomValue('12px'),
        globalValues
    ) || '12px';
    const statusIndicatorBackground = resolveFieldValue(
        (settings as any).statusIndicatorBackground || createCustomValue('#4ADE80'),
        globalValues
    ) || '#4ADE80';
    const statusIndicatorBorderWidth = resolveFieldValue(
        (settings as any).statusIndicatorBorderWidth || createCustomValue('2px'),
        globalValues
    ) || '2px';
    const statusIndicatorBorderColor = resolveFieldValue(
        (settings as any).statusIndicatorBorderColor || createCustomValue('#FFFFFF'),
        globalValues
    ) || '#FFFFFF';

    // Action buttons (styles only)
    const actionBtnMinSize = settings.actionButtonSize ? resolveFieldValue(settings.actionButtonSize, globalValues) : '36px';
    const actionIconSizeRaw = settings.actionIconSize ? resolveFieldValue(settings.actionIconSize, globalValues) : '18px';
    const actionIconSize = parseInt(actionIconSizeRaw, 10) || 18;

    const resolveActionButton = (btn: Record<string, unknown> | undefined, hovered: boolean) => {
        const bg = btn && btn.backgroundColor ? resolveFieldValue(btn.backgroundColor as FieldValue, globalValues) : 'transparent';
        const fg = btn && btn.textColor ? resolveFieldValue(btn.textColor as FieldValue, globalValues) : textColor;
        const borderType = (btn?.borderType as string) || 'none';
        const borderColor = btn && btn.borderColor ? resolveFieldValue(btn.borderColor as FieldValue, globalValues) : 'transparent';
        const boxShadow = btn && btn.boxShadow ? resolveFieldValue(btn.boxShadow as FieldValue, globalValues) : 'none';
        const borderWidth = btn?.borderWidth as { top?: string; right?: string; bottom?: string; left?: string } | undefined;
        const borderRadiusRaw = btn?.borderRadius as unknown;
        const borderRadiusCSS = resolveBorderRadiusToShorthand(borderRadiusRaw as FieldValue | string | undefined, globalValues, '9999px');
        const borderRadius = parseBorderRadiusShorthand(borderRadiusCSS);
        const paddingObj = btn?.padding as { top?: string; right?: string; bottom?: string; left?: string } | undefined;
        const duration = (btn?.transitionDuration as string) || '150ms';

        const hover = btn?.hover as Record<string, unknown> | undefined;
        const hBg = hover?.backgroundColor ? resolveFieldValue(hover.backgroundColor as FieldValue, globalValues) : bg;
        const hFg = hover?.iconColor
            ? resolveFieldValue(hover.iconColor as FieldValue, globalValues)
            : (hover?.textColor ? resolveFieldValue(hover.textColor as FieldValue, globalValues) : fg);
        const hBorderColor = hover?.borderColor ? resolveFieldValue(hover.borderColor as FieldValue, globalValues) : borderColor;
        const hShadow = hover?.boxShadow ? resolveFieldValue(hover.boxShadow as FieldValue, globalValues) : boxShadow;

        const css: React.CSSProperties = {
            display: 'flex',
            alignItems: 'center',
            justifyContent: 'center',
            minWidth: actionBtnMinSize,
            minHeight: actionBtnMinSize,
            cursor: 'pointer',
            color: hovered ? hFg : fg,
            background: hovered ? hBg : bg,
            borderStyle: borderType === 'none' ? 'none' : borderType,
            borderColor: hovered ? hBorderColor : borderColor,
            borderWidth: borderWidth ? `${borderWidth.top} ${borderWidth.right} ${borderWidth.bottom} ${borderWidth.left}` : undefined,
            borderRadius: `${borderRadius.topLeft} ${borderRadius.topRight} ${borderRadius.bottomRight} ${borderRadius.bottomLeft}`,
            padding: paddingObj ? `${paddingObj.top} ${paddingObj.right} ${paddingObj.bottom} ${paddingObj.left}` : undefined,
            boxShadow: (hovered ? hShadow : boxShadow) === 'none' ? undefined : (hovered ? hShadow : boxShadow),
            transition: `all ${duration} ease`,
        };

        return css;
    };

    const avatarIconSizeRaw = resolveFieldValue((settings as any).avatarIconSize || createCustomValue('18px'), globalValues) || '18px';
    const avatarIconSize = Number.parseInt(String(avatarIconSizeRaw), 10) || 18;
    const avatarBorderStyle = (settings as any).avatarBorderStyle || 'solid';

    // Helper to render button icon from ButtonStyleSettings.icon (dynamic icon + size)
    const renderButtonIcon = (
        btn: Record<string, unknown> | undefined,
        fallbackIcon: string,
        fallbackSize: number,
        hovered: boolean
    ) => {
        const iconSettings = btn?.icon as { icon?: string; size?: string; color?: FieldValue; hoverColor?: FieldValue } | undefined;
        const iconName = iconSettings?.icon || fallbackIcon;
        const iconSizeRaw = iconSettings?.size || `${fallbackSize}px`;
        const iconSize = parseInt(iconSizeRaw, 10) || fallbackSize;
        
        // Get icon color - use button textColor as currentColor, but icon.color/hoverColor if explicitly set
        const normalColor = iconSettings?.color 
            ? resolveFieldValue(iconSettings.color, globalValues) 
            : (btn?.textColor ? resolveFieldValue(btn.textColor as FieldValue, globalValues) : 'currentColor');
        const hoverColor = iconSettings?.hoverColor
            ? resolveFieldValue(iconSettings.hoverColor, globalValues)
            : (btn?.hover as Record<string, unknown>)?.textColor 
                ? resolveFieldValue((btn?.hover as Record<string, unknown>).textColor as FieldValue, globalValues)
                : normalColor;
        const color = hovered ? hoverColor : normalColor;

        const IconComponent = (HEADER_LUCIDE_ICON_MAP as Record<string, React.ComponentType<{ size?: number; color?: string }>>)[iconName] 
            || (HEADER_LUCIDE_ICON_MAP as Record<string, React.ComponentType<{ size?: number; color?: string }>>)[fallbackIcon];
        
        return IconComponent ? <IconComponent size={iconSize} color={color} /> : null;
    };

    const renderAvatarIcon = () => {
        const raw = String((settings as any).avatarIcon || 'bot');
        const legacyMap: Record<string, HeaderAvatarIconName> = {
            robot: 'bot',
            chat: 'message-circle',
            message: 'message-circle',
            sparkles: 'sparkles',
            headphones: 'headphones',
        };
        const normalized = (legacyMap[raw] || raw) as HeaderAvatarIconName;
        const IconComponent = (HEADER_LUCIDE_ICON_MAP as Record<string, unknown>)[normalized]
            ? (HEADER_LUCIDE_ICON_MAP as Record<HeaderAvatarIconName, React.ComponentType<{ size?: number; color?: string }>>)[normalized]
            : Bot;
        return <IconComponent size={avatarIconSize} color={avatarIconColor} />;
    };

    return (
        <div 
            className="chat-simulator-header"
            style={{
                background: bgColor,
                color: textColor,
                height,
                padding,
                display: 'flex',
                alignItems: 'center',
                justifyContent: 'space-between',
                // Header should only round the top corners to avoid seams with the window body
                borderRadius: `${headerCorners.topLeft} ${headerCorners.topRight} 0 0`,
                borderStyle: headerBorderStyle === 'none' ? 'none' : headerBorderStyle,
                borderTopWidth: headerBorderStyle === 'none' ? undefined : headerBorderWidth.top,
                borderRightWidth: headerBorderStyle === 'none' ? undefined : headerBorderWidth.right,
                borderBottomWidth: headerBorderStyle === 'none' ? undefined : headerBorderWidth.bottom,
                borderLeftWidth: headerBorderStyle === 'none' ? undefined : headerBorderWidth.left,
                borderColor: headerBorderStyle === 'none' ? undefined : headerBorderColor,
                flexShrink: 0,
                fontFamily,
                fontSize,
                fontWeight,
                fontStyle,
                textTransform: textTransform as React.CSSProperties['textTransform'],
                letterSpacing,
                textDecoration,
                lineHeight,
                textShadow: textShadow !== 'none' ? textShadow : undefined,
            }}
        >
            <div style={{ display: 'flex', alignItems: 'center', gap: '12px' }}>
                <div
                    style={{
                        position: 'relative',
                        width: avatarSize,
                        height: avatarSize,
                        borderRadius: avatarBorderRadius,
                        background: avatarBackground,
                        borderTopWidth: avatarBorderWidth.top,
                        borderRightWidth: avatarBorderWidth.right,
                        borderBottomWidth: avatarBorderWidth.bottom,
                        borderLeftWidth: avatarBorderWidth.left,
                        borderStyle: avatarBorderStyle === 'none' ? 'none' : avatarBorderStyle,
                        borderColor: avatarBorderColor,
                        display: 'flex',
                        alignItems: 'center',
                        justifyContent: 'center',
                    }}
                >
                    {renderAvatarIcon()}
                    <span
                        style={{
                            position: 'absolute',
                            bottom: 0,
                            right: 0,
                            width: statusIndicatorSize,
                            height: statusIndicatorSize,
                            borderRadius: '9999px',
                            background: statusIndicatorBackground,
                            borderStyle: 'solid',
                            borderWidth: statusIndicatorBorderWidth,
                            borderColor: statusIndicatorBorderColor,
                            boxSizing: 'border-box',
                        }}
                    />
                </div>
                <div>
                    <div style={{ 
                        fontWeight: fontWeight || 600, 
                        fontSize: fontSize || '15px',
                        fontFamily: fontFamily || 'inherit',
                        fontStyle: fontStyle || 'normal',
                        textTransform: (textTransform || 'none') as React.CSSProperties['textTransform'],
                        letterSpacing: letterSpacing || 'normal',
                        textDecoration: textDecoration || 'none',
                        lineHeight: lineHeight || '1.4',
                        textShadow: textShadow !== 'none' ? textShadow : undefined,
                    }}>
                        {settings.title || 'BoostBot'}
                    </div>
                    <div style={{
                        opacity: 0.8,
                        fontFamily: subtitleFontFamily,
                        fontSize: subtitleFontSize,
                        fontWeight: subtitleFontWeight,
                        lineHeight: subtitleLineHeight,
                        letterSpacing: subtitleLetterSpacing,
                        textTransform: subtitleTextTransform as React.CSSProperties['textTransform'],
                        fontStyle: subtitleFontStyle,
                        textDecoration: subtitleTextDecoration,
                        textShadow: subtitleTextShadow !== 'none' ? subtitleTextShadow : undefined,
                    }}>
                        {t(settings.subtitle || 'Online')}
                    </div>
                </div>
            </div>
            <div style={{ display: 'flex', alignItems: 'center', gap: '8px' }}>
                {/* Reset chat button - uses dynamic icon from ButtonStyleSettings.icon */}
                <button
                    style={resolveActionButton(settings.resetButtonStyle as unknown as Record<string, unknown> | undefined, isResetHovered)}
                    onMouseEnter={() => setIsResetHovered(true)}
                    onMouseLeave={() => setIsResetHovered(false)}
                >
                    {renderButtonIcon(
                        settings.resetButtonStyle as unknown as Record<string, unknown> | undefined,
                        'rotate-ccw',
                        actionIconSize,
                        isResetHovered
                    )}
                </button>
                {settings.showMinimizeButton && (
                    <button
                        style={resolveActionButton(settings.minimizeButtonStyle as unknown as Record<string, unknown> | undefined, isMinimizeHovered)}
                        onMouseEnter={() => setIsMinimizeHovered(true)}
                        onMouseLeave={() => setIsMinimizeHovered(false)}
                    >
                        {renderButtonIcon(
                            settings.minimizeButtonStyle as unknown as Record<string, unknown> | undefined,
                            'minus',
                            actionIconSize,
                            isMinimizeHovered
                        )}
                    </button>
                )}
                {/* Close button - uses dynamic icon from ButtonStyleSettings.icon */}
                {settings.showCloseButton && (
                    <button 
                        style={resolveActionButton(settings.closeButtonStyle as unknown as Record<string, unknown> | undefined, isCloseHovered)}
                        onMouseEnter={() => setIsCloseHovered(true)}
                        onMouseLeave={() => setIsCloseHovered(false)}
                    >
                        {renderButtonIcon(
                            settings.closeButtonStyle as unknown as Record<string, unknown> | undefined,
                            'x',
                            actionIconSize,
                            isCloseHovered
                        )}
                    </button>
                )}
            </div>
        </div>
    );
};

interface MessageBubbleProps {
    message: ChatMessage;
    userSettings: ElementSettings['userMessage'];
    botSettings: ElementSettings['botMessage'];
    globalValues: PresetGlobalValues;
    isRTL?: boolean;
}

const MessageBubble: React.FC<MessageBubbleProps> = ({
    message,
    userSettings,
    botSettings,
    globalValues,
    isRTL = true,
}) => {
    const isUser = message.type === 'user';
    const settings = isUser ? userSettings : botSettings;
    
    const bgColor = resolveFieldValue(settings.background, globalValues);
    const textColor = resolveFieldValue(settings.text, globalValues);
    const borderRadius = resolveFieldValue(settings.borderRadius, globalValues);
    const padding = resolveFieldValue(settings.padding, globalValues);
    const maxWidth = resolveFieldValue(settings.maxWidth, globalValues);
    
    // Get global typography for fallbacks
    const globalFontFamily = globalValues.typography?.fontFamily || 'inherit';
    const globalBody = globalValues.typography?.body;
    
    // Get typography settings (with global values as fallbacks)
    const typography = settings.typography || {};
    const fontSize = typography.fontSize 
        ? resolveFieldValue(typography.fontSize, globalValues) 
        : (settings.fontSize ? resolveFieldValue(settings.fontSize, globalValues) : (globalBody?.fontSize || '14px'));
    const fontFamily = typography.fontFamily ? resolveFieldValue(typography.fontFamily, globalValues) : globalFontFamily;
    const fontWeight = typography.fontWeight ? resolveFieldValue(typography.fontWeight, globalValues) : (globalBody?.fontWeight || '400');
    const fontStyle = typography.fontStyle ? resolveFieldValue(typography.fontStyle, globalValues) : 'normal';
    const textTransform = typography.textTransform ? resolveFieldValue(typography.textTransform, globalValues) : 'none';
    const textDecoration = typography.textDecoration ? resolveFieldValue(typography.textDecoration, globalValues) : 'none';
    const lineHeight = typography.lineHeight ? resolveFieldValue(typography.lineHeight, globalValues) : (globalBody?.lineHeight || '1.5');
    const letterSpacing = typography.letterSpacing ? resolveFieldValue(typography.letterSpacing, globalValues) : 'normal';
    const textShadow = typography.textShadow ? resolveFieldValue(typography.textShadow, globalValues) : 'none';
    const textAlign = typography.textAlign ? resolveFieldValue(typography.textAlign, globalValues) : 'start';

    const userTimestampSettings = (userSettings as ElementSettings['userMessage']).timestampTypography || {};
    const botTimestampSettings = (botSettings as ElementSettings['botMessage']).timestampTypography || {};
    const timestampTypography = isUser ? userTimestampSettings : botTimestampSettings;
    const timestampFontSize = timestampTypography.fontSize ? resolveFieldValue(timestampTypography.fontSize, globalValues) : '10px';
    const timestampFontFamily = timestampTypography.fontFamily ? resolveFieldValue(timestampTypography.fontFamily, globalValues) : globalFontFamily;
    const timestampFontWeight = timestampTypography.fontWeight ? resolveFieldValue(timestampTypography.fontWeight, globalValues) : '400';
    const timestampFontStyle = timestampTypography.fontStyle ? resolveFieldValue(timestampTypography.fontStyle, globalValues) : 'normal';
    const timestampTextTransform = timestampTypography.textTransform ? resolveFieldValue(timestampTypography.textTransform, globalValues) : 'none';
    const timestampTextDecoration = timestampTypography.textDecoration ? resolveFieldValue(timestampTypography.textDecoration, globalValues) : 'none';
    const timestampLineHeight = timestampTypography.lineHeight ? resolveFieldValue(timestampTypography.lineHeight, globalValues) : '1';
    const timestampLetterSpacing = timestampTypography.letterSpacing ? resolveFieldValue(timestampTypography.letterSpacing, globalValues) : '0px';
    const timestampTextShadow = timestampTypography.textShadow ? resolveFieldValue(timestampTypography.textShadow, globalValues) : 'none';
    const timestampTextAlign = timestampTypography.textAlign ? resolveFieldValue(timestampTypography.textAlign, globalValues) : 'start';
    const timestampOpacityValue = isUser
        ? resolveFieldValue(
              (userSettings as ElementSettings['userMessage']).timestampOpacity || createCustomValue('0.6'),
              globalValues
          )
        : resolveFieldValue(
              (botSettings as ElementSettings['botMessage']).timestampOpacity || createCustomValue('0.6'),
              globalValues
          );

    const showUserAvatar = (userSettings as ElementSettings['userMessage']).showAvatar !== false;
    const showBotAvatar = (botSettings as ElementSettings['botMessage']).showAvatar !== false;
    
    // Avatar sizes - match frontend defaults (32px for avatar, 16px for icon)
    // resolveFieldValue returns '' for undefined, so we add fallbacks to match frontend behavior
    const userAvatarSize = resolveFieldValue(
        (userSettings as ElementSettings['userMessage']).avatarSize || createGlobalRef('sizes.lg'),
        globalValues
    ) || '32px';
    const userAvatarBackground = resolveFieldValue(
        (userSettings as ElementSettings['userMessage']).avatarBackground || createGlobalRef('colors.border'),
        globalValues
    ) || '#E5E7EB';
    const userAvatarIconColor = resolveFieldValue(
        (userSettings as ElementSettings['userMessage']).avatarIconColor || createCustomValue('#4B5563'),
        globalValues
    ) || '#4B5563';
    const userAvatarIconSize = resolveFieldValue(
        (userSettings as ElementSettings['userMessage']).avatarIconSize || createGlobalRef('sizes.sm'),
        globalValues
    ) || '16px';
    const parsedUserAvatarIconSize = Number.parseFloat(String(userAvatarIconSize)) || 16;
    
    const botAvatarSize = resolveFieldValue(
        (botSettings as ElementSettings['botMessage']).avatarSize || createGlobalRef('sizes.lg'),
        globalValues
    ) || '32px';
    const botAvatarBackground = resolveFieldValue(
        (botSettings as ElementSettings['botMessage']).avatarBackground || createGlobalRef('colors.primarySoft'),
        globalValues
    ) || '#3BC2D020';
    const botAvatarIconColor = resolveFieldValue(
        (botSettings as ElementSettings['botMessage']).avatarIconColor || createGlobalRef('colors.primary'),
        globalValues
    ) || '#3BC2D0';
    const botAvatarIconSize = resolveFieldValue(
        (botSettings as ElementSettings['botMessage']).avatarIconSize || createGlobalRef('sizes.sm'),
        globalValues
    ) || '16px';
    const parsedBotAvatarIconSize = Number.parseFloat(String(botAvatarIconSize)) || 16;
    const timestampLabel = isUser ? '12:45' : '12:44';

    const bubbleBase: React.CSSProperties = isUser
        ? {
              background: `linear-gradient(135deg, ${bgColor} 0%, ${bgColor} 100%)`,
          }
        : {
              background: bgColor,
              boxShadow: '0 1px 2px rgba(0,0,0,0.05)',
              border: bgColor === '#FFFFFF' || bgColor === '#F9FAFB' ? '1px solid #E5E7EB' : 'none',
          };

    return (
        <div className={`bb-message-row`} style={{ display: 'flex', gap: 8, justifyContent: isUser ? 'flex-end' : 'flex-start' }}>
            {!isUser && showBotAvatar && (
                <div
                    className="bb-bot-avatar"
                    style={{
                        width: botAvatarSize,
                        height: botAvatarSize,
                        borderRadius: '50%',
                        background: botAvatarBackground,
                        display: 'flex',
                        alignItems: 'center',
                        justifyContent: 'center',
                        flexShrink: 0,
                    }}
                >
                    <Bot size={parsedBotAvatarIconSize} color={botAvatarIconColor} />
                </div>
            )}

            <div className={isUser ? 'bb-user-message-wrap' : 'bb-bot-message-wrap'} style={{ maxWidth, display: 'flex', flexDirection: 'column' }}>
                <div
                    className={`bb-message-bubble ${isUser ? 'bb-user-message' : 'bb-bot-message'}`}
                    style={{
                        ...bubbleBase,
                        color: textColor,
                        borderRadius,
                        ...(isUser ? { borderTopRightRadius: '0' } : { borderTopLeftRadius: '0' }),
                        padding,
                        maxWidth,
                        // Typography
                        fontSize,
                        fontFamily,
                        fontWeight,
                        fontStyle,
                        textTransform: textTransform as React.CSSProperties['textTransform'],
                        textDecoration,
                        lineHeight,
                        letterSpacing,
                        textShadow: textShadow !== 'none' ? textShadow : undefined,
                        direction: isRTL ? 'rtl' : 'ltr',
                        textAlign: (textAlign || 'start') as React.CSSProperties['textAlign'],
                    }}
                >
                    {message.content}
                    <span
                        className="bb-message-timestamp"
                        style={{
                            display: 'block',
                            marginTop: 4,
                            opacity: Number.parseFloat(String(timestampOpacityValue)) || 0.6,
                            fontSize: timestampFontSize,
                            fontFamily: timestampFontFamily,
                            fontWeight: timestampFontWeight as React.CSSProperties['fontWeight'],
                            fontStyle: timestampFontStyle as React.CSSProperties['fontStyle'],
                            textTransform: timestampTextTransform as React.CSSProperties['textTransform'],
                            textDecoration: timestampTextDecoration,
                            lineHeight: timestampLineHeight,
                            letterSpacing: timestampLetterSpacing,
                            textShadow: timestampTextShadow !== 'none' ? timestampTextShadow : undefined,
                            textAlign: (timestampTextAlign || 'start') as React.CSSProperties['textAlign'],
                        }}
                    >
                        {timestampLabel}
                    </span>
                </div>
                {message.element && (
                    <div className="bb-message-widget" style={{ marginTop: 8 }}>
                        {message.element}
                    </div>
                )}
            </div>
            {isUser && showUserAvatar && (
                <div
                    className="bb-user-avatar"
                    style={{
                        width: userAvatarSize,
                        height: userAvatarSize,
                        borderRadius: '50%',
                        background: userAvatarBackground,
                        display: 'flex',
                        alignItems: 'center',
                        justifyContent: 'center',
                        flexShrink: 0,
                    }}
                >
                    <User size={parsedUserAvatarIconSize} color={userAvatarIconColor} />
                </div>
            )}
        </div>
    );
};

interface TypingIndicatorProps {
    settings: ElementSettings['typingIndicator'];
    globalValues: PresetGlobalValues;
}

const TypingIndicator: React.FC<TypingIndicatorProps> = ({ settings, globalValues }) => {
    const bgColor = resolveFieldValue(settings.background, globalValues);
    const dotColor = resolveFieldValue(settings.dotColor, globalValues);
    const dotSize = resolveFieldValue(settings.dotSize, globalValues);

    return (
        <div style={{ display: 'flex', alignItems: 'flex-end', gap: '8px', marginBottom: 0 }}>
            <div 
                style={{
                    width: '32px',
                    height: '32px',
                    borderRadius: '50%',
                    background: '#3BC2D0',
                    display: 'flex',
                    alignItems: 'center',
                    justifyContent: 'center',
                    flexShrink: 0,
                }}
            >
                <Bot size={18} color="white" />
            </div>
            <div
                style={{
                    background: bgColor,
                    borderRadius: '16px',
                    padding: '12px 16px',
                    display: 'flex',
                    gap: '4px',
                    alignItems: 'center',
                }}
            >
                {[0, 1, 2].map((i) => (
                    <div
                        key={i}
                        style={{
                            width: dotSize,
                            height: dotSize,
                            borderRadius: '50%',
                            background: dotColor,
                            animation: `typingDot 1.4s ease-in-out ${i * 0.2}s infinite`,
                        }}
                    />
                ))}
            </div>
            <style>{`
                @keyframes typingDot {
                    0%, 60%, 100% { opacity: 0.3; transform: scale(1); }
                    30% { opacity: 1; transform: scale(1.2); }
                }
            `}</style>
        </div>
    );
};

interface InputAreaProps {
    settings: ElementSettings['inputArea'];
    globalValues: PresetGlobalValues;
    containerBackground: string;
    isRTL?: boolean;
    presetLanguage?: string;
}

const InputArea: React.FC<InputAreaProps> = ({ settings, globalValues, containerBackground, isRTL = true, presetLanguage }) => {
    const [isHovered, setIsHovered] = useState(false);
    
    const bgColor = resolveFieldValue(settings.background, globalValues);
    const textColor = resolveFieldValue(settings.text, globalValues);
    const borderColor = resolveFieldValue(settings.border, globalValues);
    const borderWidth = resolveFieldValue(
        (settings as unknown as { borderWidth?: FieldValue }).borderWidth || createCustomValue('1px'),
        globalValues
    );
    const borderRadius = resolveFieldValue(settings.borderRadius, globalValues);
    const padding = resolveFieldValue(settings.padding, globalValues);
    const placeholderColor = resolveFieldValue(
        (settings as unknown as { placeholderColor?: FieldValue }).placeholderColor || { type: 'custom', value: '#9CA3AF' },
        globalValues
    );
    
    // Check if new sendButton style is available
    const sendButton = (settings as unknown as { sendButton?: Record<string, unknown> }).sendButton;
    const hasNewStyle = !!sendButton;
    
    // New send button style values
    const newSendBtnBg = sendButton?.backgroundColor 
        ? resolveFieldValue(sendButton.backgroundColor as FieldValue, globalValues) 
        : '#3BC2D0';
    const newSendBtnTextColor = sendButton?.textColor 
        ? resolveFieldValue(sendButton.textColor as FieldValue, globalValues) 
        : '#FFFFFF';
    const newSendBtnHoverBg = (sendButton?.hover as Record<string, unknown>)?.backgroundColor 
        ? resolveFieldValue((sendButton?.hover as Record<string, unknown>).backgroundColor as FieldValue, globalValues) 
        : '#2BA8B5';
    const newSendBtnHoverTextColor = (sendButton?.hover as Record<string, unknown>)?.textColor 
        ? resolveFieldValue((sendButton?.hover as Record<string, unknown>).textColor as FieldValue, globalValues) 
        : '#FFFFFF';
    const newSendBtnShadow = sendButton?.boxShadow 
        ? resolveFieldValue(sendButton.boxShadow as FieldValue, globalValues) 
        : 'none';
    const newSendBtnHoverShadow = (sendButton?.hover as Record<string, unknown>)?.boxShadow 
        ? resolveFieldValue((sendButton?.hover as Record<string, unknown>).boxShadow as FieldValue, globalValues) 
        : 'none';
    const transitionDuration = (sendButton?.transitionDuration as string) || '200ms';
    
    // New send button border style values
    const newSendBtnBorderType = (sendButton?.borderType as string) || 'none';
    const newSendBtnBorderColor = sendButton?.borderColor 
        ? resolveFieldValue(sendButton.borderColor as FieldValue, globalValues) 
        : 'transparent';
    const newSendBtnBorderWidth = sendButton?.borderWidth as { top?: string; right?: string; bottom?: string; left?: string } | undefined;
    const newSendBtnBorderRadius = sendButton?.borderRadius as { topLeft?: string; topRight?: string; bottomRight?: string; bottomLeft?: string } | undefined;
    const newSendBtnHoverBorderColor = (sendButton?.hover as Record<string, unknown>)?.borderColor 
        ? resolveFieldValue((sendButton?.hover as Record<string, unknown>).borderColor as FieldValue, globalValues) 
        : newSendBtnBorderColor;
    const newSendBtnPadding = sendButton?.padding as { top?: string; right?: string; bottom?: string; left?: string } | undefined;

    // Icon values (prefer Icon accordion values when present in buttonStyle)
    const newSendBtnIconColor =
        (sendButton?.icon as Record<string, unknown> | undefined)?.color
            ? resolveFieldValue(((sendButton?.icon as Record<string, unknown>).color as FieldValue), globalValues)
            : newSendBtnTextColor;

    const newSendBtnHoverIconColor =
        (sendButton?.hover as Record<string, unknown> | undefined)?.iconColor
            ? resolveFieldValue(((sendButton?.hover as Record<string, unknown>).iconColor as FieldValue), globalValues)
            : newSendBtnHoverTextColor;

    const newSendBtnIconSizeRaw = (sendButton?.icon as Record<string, unknown> | undefined)?.size as string | undefined;
    const newSendBtnIconSize = (() => {
        const n = typeof newSendBtnIconSizeRaw === 'string' ? parseFloat(newSendBtnIconSizeRaw) : NaN;
        return Number.isFinite(n) && n > 0 ? n : 18;
    })();
    
    // Dynamic icon selection - read from sendButton.icon.icon or fallback to 'send'
    const newSendBtnIconName = ((sendButton?.icon as Record<string, unknown> | undefined)?.icon as string) || 'send';
    const DynamicSendIcon = (HEADER_LUCIDE_ICON_MAP[newSendBtnIconName as HeaderAvatarIconName] || Send) as React.ComponentType<{ size?: number; style?: React.CSSProperties }>;
    
    // Legacy send button values (fallback)
    const legacySendBtnBg = resolveFieldValue(settings.sendButtonBackground, globalValues);
    const legacySendBtnIcon = resolveFieldValue(settings.sendButtonIcon, globalValues);
    const legacySendBtnHoverBg = resolveFieldValue(settings.sendButtonHoverBackground, globalValues);
    
    // Use new style if available
    const sendBtnBg = hasNewStyle 
        ? (isHovered ? newSendBtnHoverBg : newSendBtnBg)
        : (isHovered ? legacySendBtnHoverBg : legacySendBtnBg);
    const sendBtnIcon = hasNewStyle
        ? (isHovered ? newSendBtnHoverIconColor : newSendBtnIconColor)
        : legacySendBtnIcon;
    const sendBtnShadow = hasNewStyle 
        ? (isHovered && newSendBtnHoverShadow !== 'none' ? newSendBtnHoverShadow : (newSendBtnShadow !== 'none' ? newSendBtnShadow : undefined))
        : undefined;
    
    // Get typography settings if available
    const typography = (settings as unknown as { typography?: Record<string, unknown> }).typography || {};
    const fontFamily = typography.fontFamily
        ? resolveFieldValue(typography.fontFamily as FieldValue, globalValues)
        : (globalValues.typography?.fontFamily || 'inherit');
    const fontSize = typography.fontSize
        ? resolveFieldValue(typography.fontSize as FieldValue, globalValues)
        : '14px';
    const fontWeight = typography.fontWeight
        ? resolveFieldValue(typography.fontWeight as FieldValue, globalValues)
        : '400';
    const lineHeight = typography.lineHeight
        ? resolveFieldValue(typography.lineHeight as FieldValue, globalValues)
        : '1.625';
    const letterSpacing = typography.letterSpacing
        ? resolveFieldValue(typography.letterSpacing as FieldValue, globalValues)
        : '0px';
    const textTransform = typography.textTransform
        ? resolveFieldValue(typography.textTransform as FieldValue, globalValues)
        : 'none';
    const fontStyle = typography.fontStyle
        ? resolveFieldValue(typography.fontStyle as FieldValue, globalValues)
        : 'normal';
    const textDecoration = typography.textDecoration
        ? resolveFieldValue(typography.textDecoration as FieldValue, globalValues)
        : 'none';
    const textAlign = typography.textAlign
        ? resolveFieldValue(typography.textAlign as FieldValue, globalValues)
        : 'start';
    const textShadow = typography.textShadow
        ? resolveFieldValue(typography.textShadow as FieldValue, globalValues)
        : 'none';
    const counterTypography = (settings as unknown as { counterTextTypography?: Record<string, unknown> }).counterTextTypography || {};
    const counterColor = resolveFieldValue(
        (settings as unknown as { counterTextColor?: FieldValue }).counterTextColor || createGlobalRef('colors.textSubtle'),
        globalValues
    );
    const counterFontFamily = counterTypography.fontFamily
        ? resolveFieldValue(counterTypography.fontFamily as FieldValue, globalValues)
        : (globalValues.typography?.fontFamily || 'inherit');
    const counterFontSize = counterTypography.fontSize
        ? resolveFieldValue(counterTypography.fontSize as FieldValue, globalValues)
        : '10px';
    const counterFontWeight = counterTypography.fontWeight
        ? resolveFieldValue(counterTypography.fontWeight as FieldValue, globalValues)
        : '400';
    const counterLineHeight = counterTypography.lineHeight
        ? resolveFieldValue(counterTypography.lineHeight as FieldValue, globalValues)
        : '1';
    const counterLetterSpacing = counterTypography.letterSpacing
        ? resolveFieldValue(counterTypography.letterSpacing as FieldValue, globalValues)
        : '0px';
    const counterTextTransform = counterTypography.textTransform
        ? resolveFieldValue(counterTypography.textTransform as FieldValue, globalValues)
        : 'none';
    const counterFontStyle = counterTypography.fontStyle
        ? resolveFieldValue(counterTypography.fontStyle as FieldValue, globalValues)
        : 'normal';
    const counterTextDecoration = counterTypography.textDecoration
        ? resolveFieldValue(counterTypography.textDecoration as FieldValue, globalValues)
        : 'none';
    const counterTextShadow = counterTypography.textShadow
        ? resolveFieldValue(counterTypography.textShadow as FieldValue, globalValues)
        : 'none';
    const counterTextAlign = counterTypography.textAlign
        ? resolveFieldValue(counterTypography.textAlign as FieldValue, globalValues)
        : 'center';

    return (
        <div
            className="bb-input-area"
            style={{
                background: containerBackground,
                borderTop: `${borderWidth || '1px'} solid ${borderColor}`,
                padding: '12px',
                display: 'flex',
                flexDirection: 'column',
                gap: '6px',
                flexShrink: 0,
            }}
        >
            <style>{`
              .bb-input-area .bb-input::placeholder { color: ${placeholderColor}; }
            `}</style>
            <div style={{ display: 'flex', alignItems: 'flex-end', gap: '12px' }}>
                <textarea
                    className="bb-input"
                    placeholder={
                        presetLanguage
                            ? (settings.placeholder || (presetLanguage === 'he' ? 'הקלד הודעה...' : 'Type a message...'))
                            : t(settings.placeholder || 'Type a message...')
                    }
                    disabled
                    rows={1}
                    style={{
                        flex: 1,
                        resize: 'none',
                        background: bgColor,
                        border: `${borderWidth || '1px'} solid ${borderColor}`,
                        borderRadius,
                        padding,
                        color: textColor,
                        fontFamily,
                        fontSize,
                        fontWeight: fontWeight as React.CSSProperties['fontWeight'],
                        lineHeight,
                        letterSpacing,
                        textTransform: textTransform as React.CSSProperties['textTransform'],
                        fontStyle: fontStyle as React.CSSProperties['fontStyle'],
                        textDecoration,
                        textAlign: textAlign as React.CSSProperties['textAlign'],
                        textShadow,
                        direction: isRTL ? 'rtl' : 'ltr',
                        outline: 'none',
                    }}
                />
                <button
                    className="bb-send-button"
                    onMouseEnter={() => setIsHovered(true)}
                    onMouseLeave={() => setIsHovered(false)}
                    style={{
                        // Size - use auto if padding is set, otherwise fixed 40px
                        width: hasNewStyle && newSendBtnPadding ? 'auto' : '40px',
                        height: hasNewStyle && newSendBtnPadding ? 'auto' : '40px',
                        minWidth: '40px',
                        minHeight: '40px',
                        // Padding from button style settings
                        padding: hasNewStyle && newSendBtnPadding 
                            ? `${newSendBtnPadding.top || '8px'} ${newSendBtnPadding.right || '8px'} ${newSendBtnPadding.bottom || '8px'} ${newSendBtnPadding.left || '8px'}`
                            : '0',
                        borderRadius: hasNewStyle && newSendBtnBorderRadius 
                            ? `${newSendBtnBorderRadius.topLeft || '50%'} ${newSendBtnBorderRadius.topRight || '50%'} ${newSendBtnBorderRadius.bottomRight || '50%'} ${newSendBtnBorderRadius.bottomLeft || '50%'}`
                            : '50%',
                        background: sendBtnBg,
                        ...(hasNewStyle && newSendBtnBorderType !== 'none' ? {
                            borderStyle: newSendBtnBorderType,
                            borderColor: isHovered ? newSendBtnHoverBorderColor : newSendBtnBorderColor,
                            borderTopWidth: newSendBtnBorderWidth?.top || '1px',
                            borderRightWidth: newSendBtnBorderWidth?.right || '1px',
                            borderBottomWidth: newSendBtnBorderWidth?.bottom || '1px',
                            borderLeftWidth: newSendBtnBorderWidth?.left || '1px',
                        } : { border: 'none' }),
                        boxShadow: sendBtnShadow,
                        display: 'flex',
                        alignItems: 'center',
                        justifyContent: 'center',
                        cursor: 'pointer',
                        flexShrink: 0,
                        transition: `all ${transitionDuration} ease`,
                    }}
                >
                    <DynamicSendIcon
                        size={hasNewStyle ? newSendBtnIconSize : 18}
                        style={{
                            color: sendBtnIcon,
                            transform: newSendBtnIconName === 'send' && isRTL ? 'rotate(180deg)' : undefined,
                        }}
                    />
                </button>
            </div>
            <div style={{ display: 'flex', flexDirection: 'column', gap: '4px' }}>
                <span
                    className="bb-input-counter"
                    style={{
                        color: counterColor,
                        fontFamily: counterFontFamily,
                        fontSize: counterFontSize,
                        fontWeight: counterFontWeight as React.CSSProperties['fontWeight'],
                        lineHeight: counterLineHeight,
                        letterSpacing: counterLetterSpacing,
                        textTransform: counterTextTransform as React.CSSProperties['textTransform'],
                        fontStyle: counterFontStyle as React.CSSProperties['fontStyle'],
                        textDecoration: counterTextDecoration,
                        textAlign: counterTextAlign as React.CSSProperties['textAlign'],
                        textShadow: counterTextShadow !== 'none' ? counterTextShadow : undefined,
                        display: 'block',
                    }}
                >
                    12/500
                </span>
            </div>
        </div>
    );
};

// ============================================================
// Chat Bubble (Floating Button)
// ============================================================

interface ChatBubbleButtonProps {
    settings: ElementSettings['chatBubble'];
    globalValues: PresetGlobalValues;
}

const ChatBubbleButton: React.FC<ChatBubbleButtonProps> = ({ settings, globalValues }) => {
    const resolveNumber = (value: string | undefined, fallback: number) => {
        const n = Number.parseFloat(String(value ?? ''));
        return Number.isFinite(n) ? n : fallback;
    };

    const resolveDurationSeconds = (value: string | undefined, fallback: number) => {
        const raw = String(value ?? '').trim();
        if (!raw) return fallback;
        if (raw.endsWith('ms')) {
            const n = Number.parseFloat(raw.replace('ms', ''));
            return Number.isFinite(n) ? n / 1000 : fallback;
        }
        if (raw.endsWith('s')) {
            const n = Number.parseFloat(raw.replace('s', ''));
            return Number.isFinite(n) ? n : fallback;
        }
        const n = Number.parseFloat(raw);
        return Number.isFinite(n) ? n : fallback;
    };

    const size = resolveFieldValue(settings.size, globalValues);
    const bgColor = resolveFieldValue(settings.background, globalValues);
    const icon = settings.icon || 'bot';
    const customIconUrl = settings.customIconUrl;
    const margin = (() => {
        const m = (settings as unknown as { margin?: unknown }).margin
        if (m && typeof m === 'object' && 'top' in (m as any) && 'right' in (m as any) && 'bottom' in (m as any) && 'left' in (m as any)) {
            const o = m as { top?: string; right?: string; bottom?: string; left?: string }
            return {
                top: o.top || '20px',
                right: o.right || '20px',
                bottom: o.bottom || '20px',
                left: o.left || '20px',
            }
        }
        const resolved = resolveFieldValue((m as FieldValue) || { type: 'custom', value: '20px' }, globalValues) || '20px'
        return { top: resolved, right: resolved, bottom: resolved, left: resolved }
    })();
    const position = settings.position || 'bottom-right';
    const shadow = resolveFieldValue(
        (settings as unknown as { shadow?: FieldValue }).shadow || { type: 'custom', value: '0 4px 20px rgba(0,0,0,0.2)' },
        globalValues
    );
    const borderType = (settings as unknown as { borderType?: 'none' | 'solid' | 'dashed' | 'dotted' }).borderType || 'none';
    const borderWidth = (() => {
        const bw = (settings as unknown as { borderWidth?: unknown }).borderWidth;
        if (bw && typeof bw === 'object' && 'top' in (bw as any) && 'right' in (bw as any) && 'bottom' in (bw as any) && 'left' in (bw as any)) {
            const o = bw as { top?: string; right?: string; bottom?: string; left?: string };
            return `${o.top || '0px'} ${o.right || '0px'} ${o.bottom || '0px'} ${o.left || '0px'}`;
        }
        return resolveFieldValue((bw as FieldValue) || { type: 'custom', value: '0px' }, globalValues) || '0px';
    })();
    const borderColor = resolveFieldValue((settings as unknown as { borderColor?: FieldValue }).borderColor || { type: 'custom', value: 'transparent' }, globalValues);
    const borderRadius = resolveBorderRadiusToShorthand(
        (settings as unknown as { borderRadius?: FieldValue }).borderRadius || { type: 'custom', value: '9999px' },
        globalValues,
        '9999px'
    );
    const iconColor = resolveFieldValue((settings as unknown as { iconColor?: FieldValue }).iconColor || { type: 'custom', value: '#FFFFFF' }, globalValues);

    const unreadBadge = (settings as unknown as { unreadBadge?: Record<string, unknown> }).unreadBadge || {};
    const badgeBackground = resolveFieldValue((unreadBadge as any).background || createGlobalRef('colors.error'), globalValues);
    const badgeTextColor = resolveFieldValue((unreadBadge as any).textColor || createGlobalRef('colors.textLight'), globalValues);
    const badgeSize = resolveFieldValue((unreadBadge as any).size || createGlobalRef('sizes.iconMedium'), globalValues);
    const badgeMinWidth = resolveFieldValue((unreadBadge as any).minWidth || createGlobalRef('sizes.iconMedium'), globalValues);
    const badgePaddingX = resolveFieldValue((unreadBadge as any).paddingX || createCustomValue('4px'), globalValues);
    const badgeOffsetX = resolveFieldValue((unreadBadge as any).offsetX || createCustomValue('-4px'), globalValues);
    const badgeOffsetY = resolveFieldValue((unreadBadge as any).offsetY || createCustomValue('-4px'), globalValues);
    const badgeBorderRadius = resolveBorderRadiusToShorthand(
        (unreadBadge as any).borderRadius || createGlobalRef('effects.borderRadiusFull'),
        globalValues,
        '9999px'
    );

    const badgeTypography = (unreadBadge as any).typography || {};
    const badgeFontFamily = badgeTypography.fontFamily ? resolveFieldValue(badgeTypography.fontFamily, globalValues) : (globalValues.typography?.fontFamily || 'inherit');
    const badgeFontSize = badgeTypography.fontSize ? resolveFieldValue(badgeTypography.fontSize, globalValues) : (globalValues.typography?.label?.fontSize || '12px');
    const badgeFontWeight = badgeTypography.fontWeight ? resolveFieldValue(badgeTypography.fontWeight, globalValues) : (globalValues.typography?.label?.fontWeight || '700');
    const badgeLineHeight = badgeTypography.lineHeight ? resolveFieldValue(badgeTypography.lineHeight, globalValues) : (globalValues.typography?.label?.lineHeight || '1.1');
    const badgeTextTransform = badgeTypography.textTransform ? resolveFieldValue(badgeTypography.textTransform, globalValues) : 'none';
    const badgeFontStyle = badgeTypography.fontStyle ? resolveFieldValue(badgeTypography.fontStyle, globalValues) : 'normal';
    const badgeTextDecoration = badgeTypography.textDecoration ? resolveFieldValue(badgeTypography.textDecoration, globalValues) : 'none';
    const badgeLetterSpacing = badgeTypography.letterSpacing ? resolveFieldValue(badgeTypography.letterSpacing, globalValues) : '0';
    const badgeTextShadow = badgeTypography.textShadow ? resolveFieldValue(badgeTypography.textShadow, globalValues) : 'none';
    const badgeTextAlign = badgeTypography.textAlign ? resolveFieldValue(badgeTypography.textAlign, globalValues) : 'start';

    const pulseRing = (settings as unknown as { pulseRing?: Record<string, unknown> }).pulseRing || {};
    const ringColor = resolveFieldValue((pulseRing as any).color || createGlobalRef('colors.primary'), globalValues) || bgColor;
    const ringScale = resolveNumber(resolveFieldValue((pulseRing as any).scale || createCustomValue('1.2'), globalValues), 1.2);
    const ringOpacityStart = resolveNumber(resolveFieldValue((pulseRing as any).opacityStart || createCustomValue('0.5'), globalValues), 0.5);
    const ringOpacityEnd = resolveNumber(resolveFieldValue((pulseRing as any).opacityEnd || createCustomValue('0'), globalValues), 0);
    const ringDuration = resolveDurationSeconds(
        resolveFieldValue((pulseRing as any).duration || createCustomValue('1.5s'), globalValues),
        1.5
    );

    // Hardcoded animation values (granular settings removed)
    const pulseScale = 1.05;
    const pulseDuration = 2;
    const bounceDistance = '8px';
    const bounceDuration = 0.6;
    const shakeRotation = 3;
    const shakeDuration = 0.5;
    const shakeDelay = 3;
    const shakeTotal = Math.max(0.01, shakeDuration + shakeDelay);
    const shakeActivePercent = Math.max(5, Math.min(95, (shakeDuration / shakeTotal) * 100));

    // Helper: convert hex to rgba for glow animation
    const hexToRgba = (color: string, alpha: number): string => {
        const hex = color.replace('#', '');
        if (/^[0-9a-fA-F]{6}$/.test(hex)) {
            const r = parseInt(hex.substring(0, 2), 16);
            const g = parseInt(hex.substring(2, 4), 16);
            const b = parseInt(hex.substring(4, 6), 16);
            return `rgba(${r}, ${g}, ${b}, ${alpha})`;
        }
        if (/^[0-9a-fA-F]{3}$/.test(hex)) {
            const r = parseInt(hex[0] + hex[0], 16);
            const g = parseInt(hex[1] + hex[1], 16);
            const b = parseInt(hex[2] + hex[2], 16);
            return `rgba(${r}, ${g}, ${b}, ${alpha})`;
        }
        return `rgba(59, 194, 208, ${alpha})`;
    };
    const glowColor = bgColor || '#3BC2D0';
    
    // Calculate icon size (40% of bubble size)
    const sizeNum = parseInt(size) || 60;
    const iconSizeRaw = resolveFieldValue(
        (settings as unknown as { iconSize?: FieldValue }).iconSize || { type: 'custom', value: `${Math.round(sizeNum * 0.4)}px` },
        globalValues
    );
    const iconSize = parseInt(iconSizeRaw, 10) || Math.round(sizeNum * 0.4);
    
    // Render the appropriate icon
    const renderIcon = () => {
        if (icon === 'custom' && customIconUrl) {
            return (
                <img 
                    src={customIconUrl} 
                    alt="Custom icon"
                    style={{
                        width: iconSize * 1.2,
                        height: iconSize * 1.2,
                        borderRadius: '50%',
                        objectFit: 'cover',
                    }}
                />
            );
        }

        const legacyMap: Record<string, HeaderAvatarIconName> = {
            robot: 'bot',
            chat: 'message-circle',
            message: 'message-circle',
            sparkles: 'sparkles',
            headphones: 'headphones',
        };

        const normalized = (legacyMap[String(icon)] || String(icon)) as HeaderAvatarIconName;
        const IconComponent = (HEADER_LUCIDE_ICON_MAP as Record<string, unknown>)[normalized]
            ? (HEADER_LUCIDE_ICON_MAP as Record<HeaderAvatarIconName, React.ComponentType<{ size?: number; color?: string }>>)[normalized]
            : Bot;
        
        return <IconComponent size={iconSize} color={iconColor || 'white'} />;
    };

    const positionStyles: React.CSSProperties = (() => {
        switch (position) {
            case 'bottom-left':
                return { left: margin.left, right: 'auto', bottom: margin.bottom, top: 'auto' };
            case 'top-left':
                return { left: margin.left, right: 'auto', top: margin.top, bottom: 'auto' };
            case 'top-right':
                return { right: margin.right, left: 'auto', top: margin.top, bottom: 'auto' };
            case 'bottom-right':
            default:
                return { right: margin.right, left: 'auto', bottom: margin.bottom, top: 'auto' };
        }
    })();

    return (
        <button
            type="button"
            className="bb-chat-bubble"
            style={{
                ...positionStyles,
                position: 'relative',
                width: size,
                height: size,
                borderRadius,
                background: bgColor,
                display: 'flex',
                alignItems: 'center',
                justifyContent: 'center',
                boxShadow: shadow,
                borderStyle: borderType === 'none' ? 'none' : borderType,
                borderWidth: borderType === 'none' ? '0' : (borderWidth || '0px'),
                borderColor: borderType === 'none' ? 'transparent' : (borderColor || 'transparent'),
                cursor: 'pointer',
                padding: 0,
                animation:
                    settings.animation === 'pulse'
                        ? `pulseAnimation ${pulseDuration}s infinite`
                        : settings.animation === 'bounce'
                        ? `bounceAnimation ${bounceDuration}s infinite`
                        : settings.animation === 'shake'
                        ? `shakeAnimation ${shakeTotal}s infinite`
                        : settings.animation === 'glow'
                        ? `glowAnimation 2s ease-in-out infinite`
                        : settings.animation === 'wiggle'
                        ? `wiggleAnimation 3.5s ease-in-out infinite`
                        : settings.animation === 'float'
                        ? `floatAnimation 3s ease-in-out infinite`
                        : undefined,
            }}
        >
            {/* Unread badge preview (static count) */}
            <span
                className="bb-chat-bubble-unread"
                style={{
                    position: 'absolute',
                    top: badgeOffsetY,
                    [position === 'bottom-left' || position === 'top-left' ? 'right' : 'left']: badgeOffsetX,
                    minWidth: badgeMinWidth,
                    height: badgeSize,
                    paddingLeft: badgePaddingX,
                    paddingRight: badgePaddingX,
                    borderRadius: badgeBorderRadius,
                    background: badgeBackground,
                    color: badgeTextColor,
                    display: 'flex',
                    alignItems: 'center',
                    justifyContent: 'center',
                    fontFamily: badgeFontFamily,
                    fontSize: badgeFontSize,
                    fontWeight: badgeFontWeight,
                    lineHeight: badgeLineHeight,
                    textTransform: badgeTextTransform as React.CSSProperties['textTransform'],
                    fontStyle: badgeFontStyle,
                    textDecoration: badgeTextDecoration,
                    letterSpacing: badgeLetterSpacing,
                    textShadow: badgeTextShadow !== 'none' ? badgeTextShadow : undefined,
                    textAlign: badgeTextAlign as React.CSSProperties['textAlign'],
                    pointerEvents: 'none',
                }}
            >
                3
            </span>

            {/* Pulse ring preview — hidden when animation is 'none' */}
            {settings.animation !== 'none' && (
            <span
                className="bb-chat-bubble-pulse"
                style={{
                    position: 'absolute',
                    inset: 0,
                    borderRadius,
                    backgroundColor: ringColor || bgColor,
                    animation: `pulseRing ${ringDuration}s infinite`,
                    pointerEvents: 'none',
                }}
            />
            )}
            <span className="bb-chat-bubble-icon">{renderIcon()}</span>
            <style>{`
                @keyframes pulseAnimation {
                    0%, 100% { transform: scale(1); }
                    50% { transform: scale(${pulseScale}); }
                }
                @keyframes bounceAnimation {
                    0%, 100% { transform: translateY(0); }
                    50% { transform: translateY(-${bounceDistance}); }
                }
                @keyframes shakeAnimation {
                    0% { transform: rotate(0deg); }
                    ${shakeActivePercent * 0.25}% { transform: rotate(-${shakeRotation}deg); }
                    ${shakeActivePercent * 0.5}% { transform: rotate(${shakeRotation}deg); }
                    ${shakeActivePercent * 0.75}% { transform: rotate(-${shakeRotation}deg); }
                    ${shakeActivePercent}% { transform: rotate(${shakeRotation}deg); }
                    100% { transform: rotate(0deg); }
                }
                @keyframes glowAnimation {
                    0%, 100% { box-shadow: 0 0 0px ${hexToRgba(glowColor, 0)}; }
                    50% { box-shadow: 0 0 20px ${hexToRgba(glowColor, 0.6)}; }
                }
                @keyframes wiggleAnimation {
                    0% { transform: translateX(0); }
                    3% { transform: translateX(-3px); }
                    6% { transform: translateX(3px); }
                    9% { transform: translateX(-3px); }
                    12% { transform: translateX(3px); }
                    14%, 100% { transform: translateX(0); }
                }
                @keyframes floatAnimation {
                    0%, 100% { transform: translateY(0); }
                    50% { transform: translateY(-6px); }
                }
                @keyframes pulseRing {
                    0% { transform: scale(1); opacity: ${ringOpacityStart}; }
                    60% { transform: scale(${ringScale}); opacity: ${ringOpacityEnd}; }
                    100% { transform: scale(${ringScale}); opacity: 0; }
                }
            `}</style>
        </button>
    );
};

// ============================================================
// Main Component
// ============================================================

export const ChatSimulator: React.FC<ChatSimulatorProps> = ({
    globalValues = DEFAULT_GLOBAL_VALUES,
    elementSettings = DEFAULT_ELEMENT_SETTINGS,
    messages,
    showTypingIndicator = false,
    previewElement,
    className = '',
    scale = 1,
    onRefresh,
    isRTL = true,
    presetLanguage,
}) => {
    const effectiveIsRTL = presetLanguage
        ? ['he', 'ar', 'fa'].includes(presetLanguage)
        : isRTL;

    const resolvedMessages = messages || getDefaultMessages(presetLanguage);
    /**
     * Preview parity fix:
     * The "גודל בועית" controller lives under `elementSettings.chatBubble.size` (Bubble tab),
     * but many elements (including avatars) may reference `sizes.bubbleSize` via global refs.
     * In the live widget, these end up aligned; in the admin simulator preview, a custom
     * chatBubble.size would not propagate to `globalValues.sizes.bubbleSize`, causing tiny
     * visual mismatches (notably `.bb-bot-avatar` / `.bb-user-avatar`).
     *
     * For preview purposes only, mirror the resolved chatBubble size into the global
     * `sizes.bubbleSize` slot so any global refs stay in sync.
     */
    const previewGlobalValues = useMemo(() => {
        const resolvedBubbleSize =
            resolveFieldValue(
                elementSettings?.chatBubble?.size || createGlobalRef('sizes.bubbleSize'),
                globalValues
            ) ||
            (globalValues as any)?.sizes?.bubbleSize ||
            '45px';

        return {
            ...globalValues,
            sizes: {
                ...(globalValues as any)?.sizes,
                bubbleSize: resolvedBubbleSize,
            },
        } as PresetGlobalValues;
    }, [elementSettings, globalValues]);

    // Merge messages with preview element if provided
    const displayMessages = useMemo(() => {
        if (!previewElement) return resolvedMessages;
        
        return [
            ...resolvedMessages,
            {
                id: 'preview',
                type: 'bot' as const,
                content: '',
                element: previewElement,
            },
        ];
    }, [resolvedMessages, previewElement]);

    // Get window settings
    const width = resolveFieldValue(elementSettings.chatWindow.width, globalValues);
    const height = resolveFieldValue(elementSettings.chatWindow.height, globalValues);
    const bgColor = resolveFieldValue(elementSettings.chatWindow.background, globalValues);
    const borderRadius = resolveFieldValue(elementSettings.chatWindow.borderRadius, globalValues);
    const shadow = resolveFieldValue(elementSettings.chatWindow.shadow, globalValues);
    const borderType =
        (elementSettings.chatWindow as unknown as { borderType?: 'none' | 'solid' | 'dashed' | 'dotted' }).borderType || 'solid';
    const borderWidth = (() => {
        const bw = (elementSettings.chatWindow as unknown as { borderWidth?: unknown }).borderWidth;
        if (bw && typeof bw === 'object') {
            const o = bw as Record<string, unknown>;
            if (typeof o.top === 'string' && typeof o.right === 'string' && typeof o.bottom === 'string' && typeof o.left === 'string') {
                return `${o.top} ${o.right} ${o.bottom} ${o.left}`;
            }
        }
        return resolveFieldValue((bw as FieldValue) || { type: 'custom', value: '1px' }, globalValues);
    })();
    const borderColor = resolveFieldValue(
        (elementSettings.chatWindow as unknown as { borderColor?: FieldValue }).borderColor || { type: 'custom', value: 'rgba(0,0,0,0.05)' },
        globalValues
    );
    const windowPadding = resolveFieldValue(
        (elementSettings.chatWindow as unknown as { padding?: FieldValue }).padding || { type: 'custom', value: '0' },
        globalValues
    );
    const messagesPadding = resolveFieldValue(
        (elementSettings.chatWindow as unknown as { messagesPadding?: FieldValue }).messagesPadding || { type: 'custom', value: '12px' },
        previewGlobalValues
    );
    const messagesGap = resolveFieldValue(
        (elementSettings.chatWindow as unknown as { messagesGap?: FieldValue }).messagesGap || { type: 'custom', value: '12px' },
        previewGlobalValues
    );

    return (
        <div className={`chat-simulator-wrapper ${className}`} dir={effectiveIsRTL ? 'rtl' : 'ltr'}>
            {/* Toolbar */}
            <div 
                style={{
                    display: 'flex',
                    alignItems: 'center',
                    justifyContent: 'space-between',
                    marginBottom: '16px',
                    padding: '0 4px',
                }}
            >
                <div style={{ fontSize: '14px', color: '#6B7280', fontWeight: 500 }}>
                    {t('Preview')}
                </div>
                {onRefresh && (
                    <button
                        onClick={onRefresh}
                        style={{
                            display: 'flex',
                            alignItems: 'center',
                            gap: '6px',
                            background: 'transparent',
                            border: '1px solid #E5E7EB',
                            borderRadius: '6px',
                            padding: '6px 12px',
                            fontSize: '13px',
                            color: '#6B7280',
                            cursor: 'pointer',
                        }}
                    >
                        <RefreshCw size={14} />
                        {t('Refresh')}
                    </button>
                )}
            </div>

            {/* Chat Window */}
            <div
                className="chat-simulator bb-chat-window"
                style={{
                    width,
                    maxWidth: '100%',
                    height,
                    background: bgColor,
                    borderRadius,
                    boxShadow: shadow,
                    borderStyle: borderType,
                    borderWidth: borderType === 'none' ? '0' : (borderWidth || '1px'),
                    borderColor: borderColor || 'rgba(0,0,0,0.05)',
                    display: 'flex',
                    flexDirection: 'column',
                    overflow: 'hidden',
                    ...(scale !== 1
                        ? {
                              transform: `scale(${scale})`,
                              transformOrigin: 'top center',
                          }
                        : {}),
                    margin: '0 auto',
                    // Apply global typography font to the root so 'inherit' works correctly
                    fontFamily: previewGlobalValues.typography?.fontFamily || 'inherit',
                    padding: windowPadding || '0',
                }}
            >
                {/* Header */}
                <Header 
                    settings={elementSettings.header} 
                    globalValues={previewGlobalValues} 
                />

                {/* Messages Area */}
                <div
                    className="bb-chat-window-messages"
                    style={{
                        flex: 1,
                        overflowY: 'auto',
                        display: 'flex',
                        flexDirection: 'column',
                        padding: messagesPadding || '16px',
                        gap: messagesGap || '12px',
                        direction: effectiveIsRTL ? 'rtl' : 'ltr',
                    }}
                >
                    {displayMessages.map((msg) => (
                        <MessageBubble
                            key={msg.id}
                            message={msg}
                            userSettings={elementSettings.userMessage}
                            botSettings={elementSettings.botMessage}
                            globalValues={previewGlobalValues}
                            isRTL={effectiveIsRTL}
                        />
                    ))}
                    
                    {showTypingIndicator && (
                        <TypingIndicator 
                            settings={elementSettings.typingIndicator}
                            globalValues={previewGlobalValues}
                        />
                    )}
                </div>

                {/* Input Area */}
                <InputArea
                    settings={elementSettings.inputArea}
                    globalValues={previewGlobalValues}
                    containerBackground={bgColor || '#FFFFFF'}
                    isRTL={effectiveIsRTL}
                    presetLanguage={presetLanguage}
                />
            </div>

            {/* Chat Bubble Preview */}
            <div style={{ marginTop: '24px', textAlign: 'center' }}>
                <div style={{ fontSize: '12px', color: '#9CA3AF', marginBottom: '12px' }}>
                    {t('Bubble Button')}
                </div>
                <div className="bb-chat-bubble-preview" style={{ display: 'inline-block' }}>
                    <ChatBubbleButton settings={elementSettings.chatBubble} globalValues={previewGlobalValues} />
                </div>
            </div>
        </div>
    );
};

export default ChatSimulator;

