import { useState, useEffect, useLayoutEffect, useRef, useCallback } from 'react';
import { motion, AnimatePresence } from 'framer-motion';
import {
  Phone,
  Video,
  MoreVertical,
  Search,
  X,
  ArrowDown,
  Trash2,
  UserPlus,
  Bell,
  BellOff,
  Settings,
  Eraser,
  Pin,
  Forward,
  Bookmark,
  ArrowLeft,
  MessagesSquare,
  Pencil,
} from 'lucide-react';
import { useChatStore } from '../../application/chatStore';
import { httpClient } from '../../../../core/infrastructure/httpClient';
import { useAuthStore } from '../../../auth/application/authStore';
import { ChatApi } from '../../infrastructure/chatApi';
import { getSocket } from '../../../../core/infrastructure/socket';
import { isChatMuted, toggleMuteChat } from '../../../../core/utils/sounds';
import { useLang } from '../../../../core/infrastructure/i18n';
import { formatLastSeen, getInitials, generateAvatarColor } from '../../../../core/utils/utils';
import type { UserBasic, Message } from '../../../../core/domain/types';
import MessageBubble from './MessageBubble';
import MessageInput from './MessageInput';
import TypingIndicator from './TypingIndicator';
import UserProfile from '../../../users/presentation/components/UserProfile';
import GroupSettings from './GroupSettings';
import ForwardModal from './ForwardModal';
import ConfirmModal from '../../../../core/presentation/components/ui/ConfirmModal';
import Avatar from '../../../../core/presentation/components/ui/Avatar';
import { useThemeStore } from '../../../../core/application/stores/themeStore';

export default function ChatView({ onStartCall, onStartGroupCall }: { onStartCall?: (targetUser: UserBasic, type: 'voice' | 'video') => void; onStartGroupCall?: (chatId: string, chatName: string, type: 'voice' | 'video') => void }) {
  const { user, config } = useAuthStore();
  const { t, lang } = useLang();
  const { chatTheme } = useThemeStore();
  const {
    activeChat,
    chats,
    messages,
    typingUsers,
    pinnedMessages,
    isLoadingMessages,
    hasMoreMessages,
    loadMessages,
    setActiveChat,
    loadChats,
  } = useChatStore();

  const [showTopMenu, setShowTopMenu] = useState(false);
  const [showSearch, setShowSearch] = useState(false);
  const [searchText, setSearchText] = useState('');
  const [searchResults, setSearchResults] = useState<Message[]>([]);
  const [profileUserId, setProfileUserId] = useState<string | null>(null);
  const [showGroupSettings, setShowGroupSettings] = useState(false);
  const [showScrollDown, setShowScrollDown] = useState(false);
  const [stickyDate, setStickyDate] = useState<string | null>(null);
  const [showStickyDate, setShowStickyDate] = useState(false);
  const stickyDateTimerRef = useRef<any>(null);
  const [muted, setMuted] = useState(false);

  const [selectionMode, setSelectionMode] = useState(false);
  const [selectedMessages, setSelectedMessages] = useState<Set<string>>(new Set());
  const [showForwardModal, setShowForwardModal] = useState(false);
  const [showDeleteMenu, setShowDeleteMenu] = useState(false);
  const [confirmAction, setConfirmAction] = useState<{ message: string; action: () => void } | null>(null);
  const [scrollReady, setScrollReady] = useState(false);
  const [activeGroupCallParticipants, setActiveGroupCallParticipants] = useState<string[]>([]);

  const messagesEndRef = useRef<HTMLDivElement>(null);
  const scrollContainerRef = useRef<HTMLDivElement>(null);

  const handleJumpToMessage = async (msgId: string, sequenceId?: number) => {
    const tryScroll = () => {
      const el = document.getElementById(`msg-${msgId}`);
      if (el) {
        el.scrollIntoView({ behavior: 'smooth', block: 'center' });
        el.classList.add('highlight-message');
        setTimeout(() => el.classList.remove('highlight-message'), 5000);
        return true;
      }
      return false;
    };

    if (tryScroll()) return;
    if (!activeChat) return;

    const NotificationStore = await import('../../../../core/application/stores/notificationStore');
    NotificationStore.useNotificationStore.getState().addNotification('info', (t as any)('searchingHistory') || 'Searching message in history...');

    const chatStore = useChatStore.getState();

    if (sequenceId !== undefined) {
      await chatStore.jumpToMessage(activeChat, sequenceId);
      // Wait a bit for React to render
      setTimeout(() => {
        if (!tryScroll()) {
          NotificationStore.useNotificationStore.getState().addNotification('warning', (t as any)('messageNotFound') || 'Message not found');
        }
      }, 300);
    } else {
      // Old fallback loop if no sequenceId
      let found = false;
      for (let i = 0; i < 50; i++) {
        await chatStore.loadMessages(activeChat, false, true);
        await new Promise(resolve => setTimeout(resolve, 150));
        if (tryScroll()) { found = true; break; }
      }
      if (!found) {
        NotificationStore.useNotificationStore.getState().addNotification('warning', (t as any)('messageNotFound') || 'Message not found');
      }
    }
  };
  const searchInputRef = useRef<HTMLInputElement>(null);
  const topMenuRef = useRef<HTMLDivElement>(null);
  const deleteMenuRef = useRef<HTMLDivElement>(null);
  const chatViewRef = useRef<HTMLDivElement>(null);

  const chat = chats.find((c) => c.id === activeChat);
  const allChatMessages = activeChat ? messages[activeChat] || [] : [];
  // Filter out deleted messages to prevent layout shifts
  const chatMessages = allChatMessages.filter(m => !m.isDeleted);
  const chatPinnedMessages = activeChat ? pinnedMessages[activeChat] || [] : [];
  const [pinnedIndex, setPinnedIndex] = useState(0);

  const [importStatus, setImportStatus] = useState<{ processed: number, total: number, status: string } | null>(null);
  const isAtBottomRef = useRef(false);

  useEffect(() => {
    if (!chat?.isImporting || !chat?.importJobId) {
      setImportStatus(null);
      return;
    }

    const poll = async () => {
      try {
        const data = await httpClient.request<any>(`/import/telegram/status/${chat.importJobId}`);
        setImportStatus({ processed: data.processedMessages, total: data.totalMessages, status: data.status });
        if (data.status === 'Completed' || data.status === 'Failed') {
          setImportStatus(null);
          loadChats();
        }
      } catch (e: any) {
        if (e.status === 404) {
          console.warn('Import job not found');
        } else {
          console.error('Failed to poll status', e);
        }
      }
    };

    poll();
    const interval = setInterval(poll, 1000);
    return () => clearInterval(interval);
  }, [chat?.isImporting, chat?.importJobId]);

  // Количество непрочитанных сообщений (для бейджика)
  const unreadCount = chatMessages.filter(
    (m) => m.senderId !== user?.id && !m.readBy?.some((r) => r.userId === user?.id)
  ).length;

  const otherMember = chat?.members.find((m) => m.user.id !== user?.id);
  const isFavorites = chat?.type === 'favorites';
  const chatName = isFavorites
    ? t('favorites')
    : chat?.type === 'personal'
      ? otherMember?.user.displayName || otherMember?.user.userName || otherMember?.user.username || t('chat')
      : chat?.name || t('group');
  const chatAvatar = isFavorites
    ? null
    : chat?.type === 'personal'
      ? otherMember?.user.avatarUrl || otherMember?.user.avatar || null
      : chat?.avatarUrl || chat?.avatar || null;
  const isOnline = chat?.type === 'personal' && otherMember?.user.isOnline;

  const typingInChat = typingUsers.filter((t) => t.chatId === activeChat && t.userId !== user?.id);

  // Refs and logic for tracking session's first unread message to show the divider exactly once per load
  const sessionUnreadRef = useRef<{ chatId: string, msgId: string | null }>({ chatId: '', msgId: null });

  if (activeChat && activeChat !== sessionUnreadRef.current.chatId && !isLoadingMessages) {
    const firstUnreadMsg = chatMessages.find(
      (m) => m.senderId !== user?.id && !m.readBy?.some((r) => r.userId === user?.id)
    );
    sessionUnreadRef.current = { chatId: activeChat, msgId: firstUnreadMsg ? firstUnreadMsg.id : null };
  }
  const firstUnreadId = activeChat === sessionUnreadRef.current.chatId ? sessionUnreadRef.current.msgId : null;
  const initialScrollChatId = useRef<string | null>(null);

  // Load muted state
  useEffect(() => {
    if (activeChat) {
      setMuted(isChatMuted(activeChat));
      setActiveGroupCallParticipants([]);
    }
  }, [activeChat]);

  // Listen for active group calls
  useEffect(() => {
    const socket = getSocket();
    if (!socket) return;
    const handler = (data: { chatId: string; participants: string[] }) => {
      if (data.chatId === activeChat) {
        setActiveGroupCallParticipants(data.participants.filter(p => p !== user?.id));
      }
    };
    socket.on('group_call_active', handler);
    // Request current status when opening a group chat
    if (activeChat && chat?.type === 'group') {
      socket.emit('get_group_call_status', { chatId: activeChat });
    }
    return () => { socket.off('group_call_active', handler); };
  }, [activeChat, user?.id, chat?.type]);

  // Close top menu on click outside
  useEffect(() => {
    if (!showTopMenu) return;
    const handleClick = (e: MouseEvent) => {
      if (topMenuRef.current && !topMenuRef.current.contains(e.target as Node)) {
        setShowTopMenu(false);
      }
    };
    // Use setTimeout to avoid the same click that opened the menu from closing it
    const timer = setTimeout(() => document.addEventListener('click', handleClick), 0);
    return () => {
      clearTimeout(timer);
      document.removeEventListener('click', handleClick);
    };
  }, [showTopMenu]);

  // Close delete menu on click outside
  useEffect(() => {
    if (!showDeleteMenu) return;
    const handleClick = (e: MouseEvent) => {
      if (deleteMenuRef.current && !deleteMenuRef.current.contains(e.target as Node)) {
        setShowDeleteMenu(false);
      }
    };
    const timer = setTimeout(() => document.addEventListener('click', handleClick), 0);
    return () => {
      clearTimeout(timer);
      document.removeEventListener('click', handleClick);
    };
  }, [showDeleteMenu]);

  // Прокрутка вниз
  const scrollToBottom = useCallback((smooth = true) => {
    if (messagesEndRef.current) {
      messagesEndRef.current.scrollIntoView({ behavior: smooth ? 'smooth' : 'instant', block: 'end' });
    } else if (scrollContainerRef.current) {
      scrollContainerRef.current.scrollTop = scrollContainerRef.current.scrollHeight;
    }
  }, []);

  const isInitializingRef = useRef(false);
  const isScrollingToBottomRef = useRef(false);
  const scrollTimeoutRef = useRef<any>(null);
  const prevChatIdRef = useRef<string | null>(activeChat);

  // 1. СОХРАНЕНИЕ ПОЗИЦИИ (ЯКОРНОЕ ПО MESSAGE ID)
  const saveScrollPosition = useCallback((targetChatId?: string) => {
    const container = scrollContainerRef.current;
    const chatId = targetChatId || activeChat;

    if (!container || !chatId || !scrollReady || isInitializingRef.current || isScrollingToBottomRef.current) return;

    // Проверка: сообщения в стейте должны быть от целевого чата
    if (chatMessages.length > 0 && chatMessages[0].chatId !== chatId) return;

    const isAtBottomNow = container.scrollHeight - container.scrollTop - container.clientHeight < 40;
    isAtBottomRef.current = isAtBottomNow;

    if (isAtBottomNow) {
      localStorage.setItem(`chat_at_bottom_${chatId}`, 'true');
      localStorage.removeItem(`chat_anchor_${chatId}`);
      return;
    }

    const messageElements = container.querySelectorAll('[data-message-id]');
    if (messageElements.length === 0) return;

    let anchor = null;
    const containerRect = container.getBoundingClientRect();

    // Находим первое сообщение, которое пересекает верхнюю границу видимости
    for (const el of messageElements) {
      const rect = el.getBoundingClientRect();
      if (rect.bottom > containerRect.top) {
        anchor = {
          id: el.getAttribute('data-message-id'),
          offset: rect.top - containerRect.top
        };
        break;
      }
    }

    if (anchor && anchor.id) {
      localStorage.setItem(`chat_anchor_${chatId}`, JSON.stringify(anchor));
      localStorage.removeItem(`chat_at_bottom_${chatId}`);
    }
  }, [activeChat, scrollReady, chatMessages]);

  // 2. ВОССТАНОВЛЕНИЕ ПОЗИЦИИ
  const restoreScrollPosition = useCallback(() => {
    const container = scrollContainerRef.current;
    if (!container || !activeChat) return false;

    if (chatMessages.length > 0 && chatMessages[0].chatId !== activeChat) return false;
    if (chatMessages.length === 0) return true;

    // ПРИОРИТЕТ 1: Если чат внизу (после второго клика или скролла)
    if (localStorage.getItem(`chat_at_bottom_${activeChat}`) === 'true') {
      container.scrollTop = container.scrollHeight;
      isAtBottomRef.current = true;
      return true;
    }

    // ПРИОРИТЕТ 2: Восстановление по якорю сообщения
    const saved = localStorage.getItem(`chat_anchor_${activeChat}`);
    if (saved) {
      try {
        const { id, offset } = JSON.parse(saved);
        let el = container.querySelector(`[data-message-id="${id}"]`) as HTMLElement;

        // Поиск ближайшего, если точное сообщение еще не загружено
        if (!el) {
          const msgIndex = chatMessages.findIndex(m => m.id === id);
          if (msgIndex !== -1) {
            for (let i = msgIndex; i < chatMessages.length; i++) {
              const nextEl = container.querySelector(`[data-message-id="${chatMessages[i].id}"]`) as HTMLElement;
              if (nextEl) { el = nextEl; break; }
            }
          }
        }

        if (el) {
          container.scrollTop = el.offsetTop - offset;
          return true;
        }
      } catch (e) { console.error('Anchor restoration failed', e); }
    }

    // ПРИОРИТЕТ 3: Непрочитанные или низ
    const firstUnread = chatMessages.find(m => m.senderId !== user?.id && !m.readBy?.some(r => r.userId === user?.id));
    if (firstUnread) {
      const el = document.getElementById(`msg-${firstUnread.id}`) || document.getElementById('unread-divider');
      if (el) {
        container.scrollTop = (el as HTMLElement).offsetTop - 80;
        return true;
      }
    }

    container.scrollTop = container.scrollHeight;
    isAtBottomRef.current = true;
    return true;
  }, [activeChat, chatMessages, user?.id]);

  // 3. ОБЗЕРВЕР И УПРАВЛЕНИЕ ЖИЗНЕННЫМ ЦИКЛОМ
  useEffect(() => {
    if (isLoadingMessages || !scrollContainerRef.current || !activeChat) return;
    const container = scrollContainerRef.current;

    const observer = new ResizeObserver(() => {
      if (isInitializingRef.current) return;

      if (!scrollReady) {
        if (restoreScrollPosition()) {
          setScrollReady(true);
          isInitializingRef.current = false;
        }
      } else if (isAtBottomRef.current) {
        // Удержание внизу при росте контента
        container.scrollTop = container.scrollHeight;
      }
    });

    const messagesDiv = container.querySelector('.space-y-1');
    if (messagesDiv) observer.observe(messagesDiv);

    // Попытка восстановления при появлении правильных сообщений
    if (chatMessages.length > 0 && chatMessages[0].chatId === activeChat && !scrollReady) {
      if (restoreScrollPosition()) {
        setScrollReady(true);
        isInitializingRef.current = false;
      }
    }

    return () => observer.disconnect();
  }, [activeChat, isLoadingMessages, chatMessages, restoreScrollPosition, scrollReady]);

  // 4. ПЕРЕКЛЮЧЕНИЕ ЧАТОВ (СИНХРОННОЕ)
  useLayoutEffect(() => {
    if (activeChat !== prevChatIdRef.current) {
      isInitializingRef.current = true;
      isScrollingToBottomRef.current = false;

      // Сохраняем позицию старого чата
      if (prevChatIdRef.current && scrollContainerRef.current && scrollReady) {
        saveScrollPosition(prevChatIdRef.current);
      }

      setScrollReady(false);
      prevChatIdRef.current = activeChat;

      if (scrollContainerRef.current) {
        scrollContainerRef.current.scrollTop = 0;
      }

      const timer = setTimeout(() => {
        isInitializingRef.current = false;
      }, 600);

      return () => clearTimeout(timer);
    }
  }, [activeChat, saveScrollPosition, scrollReady]);

  const checkScrollPosition = useCallback(() => {
    const container = scrollContainerRef.current;
    if (!container || isInitializingRef.current) return;
    const isNearBottom = container.scrollHeight - container.scrollTop - container.clientHeight < 300;
    setShowScrollDown(!isNearBottom);
  }, []);

  const lastScrollTopRef = useRef(0);
  const handleScroll = () => {
    if (isInitializingRef.current || isScrollingToBottomRef.current) return;

    checkScrollPosition();
    const container = scrollContainerRef.current;
    if (container && activeChat) {
      // Synchronous "at bottom" check to prevent ResizeObserver from fighting the user
      const isAtBottomNow = container.scrollHeight - container.scrollTop - container.clientHeight < 40;
      isAtBottomRef.current = isAtBottomNow;

      if (scrollTimeoutRef.current) clearTimeout(scrollTimeoutRef.current);
      scrollTimeoutRef.current = setTimeout(() => saveScrollPosition(), 150);

      const st = container.scrollTop;
      const isScrollingUp = st < lastScrollTopRef.current;
      const stChanged = st !== lastScrollTopRef.current;

      // Sticky Date Header Logic - Telegram style
      if (st > 100 && stChanged) {
        // Показываем плашку только при прокрутке или если она уже активна
        // При прокрутке вверх она должна быть видна всегда
        if (isScrollingUp) {
          setShowStickyDate(true);
          if (stickyDateTimerRef.current) clearTimeout(stickyDateTimerRef.current);
          // Таймер на 2 сек запустится только после остановки скролла
          stickyDateTimerRef.current = setTimeout(() => setShowStickyDate(false), 2000);
        } else {
          // При прокрутке вниз плашка обычно скрывается быстрее
          if (stickyDateTimerRef.current) {
            clearTimeout(stickyDateTimerRef.current);
            stickyDateTimerRef.current = setTimeout(() => setShowStickyDate(false), 800);
          }
        }
      } else if (st <= 100) {
        setShowStickyDate(false);
        if (stickyDateTimerRef.current) clearTimeout(stickyDateTimerRef.current);
      }

      lastScrollTopRef.current = st;

      const containerRect = container.getBoundingClientRect();
      const messageElements = container.querySelectorAll('[data-message-id]');

      let currentTopMsgId = null;
      for (const el of messageElements) {
        const rect = el.getBoundingClientRect();
        if (rect.top >= containerRect.top) {
          currentTopMsgId = el.getAttribute('data-message-id');
          break;
        }
      }

      if (currentTopMsgId) {
        const msg = chatMessages.find(m => m.id === currentTopMsgId);
        if (msg) {
          const dateStr = new Date(msg.createdAt).toLocaleDateString(lang === 'ru' ? 'ru' : 'en', {
            day: 'numeric',
            month: 'long',
          });
          if (dateStr !== stickyDate) setStickyDate(dateStr);
        }
      }

      if (container.scrollTop < 100 && hasMoreMessages[activeChat] && !isLoadingMessages) {
        useChatStore.getState().loadMessages(activeChat, false, true);
      }
    }
  };

  useEffect(() => {
    const handleScrollEvent = (e: any) => {
      if (e.detail?.chatId === activeChat) {
        // Принудительный сброс режима (Второй Клик)
        localStorage.setItem(`chat_at_bottom_${activeChat}`, 'true');
        localStorage.removeItem(`chat_anchor_${activeChat}`);

        isScrollingToBottomRef.current = true;
        if (scrollContainerRef.current) {
          scrollContainerRef.current.scrollTo({
            top: scrollContainerRef.current.scrollHeight,
            behavior: 'smooth'
          });
        }

        setTimeout(() => {
          isScrollingToBottomRef.current = false;
        }, 1000);
      }
    };
    window.addEventListener('CHAT_SCROLL_TO_BOTTOM', handleScrollEvent);
    return () => window.removeEventListener('CHAT_SCROLL_TO_BOTTOM', handleScrollEvent);
  }, [activeChat]);

  // Read receipts using IntersectionObserver
  const sentReadIdsRef = useRef<Set<string>>(new Set());
  const observerRef = useRef<IntersectionObserver | null>(null);

  useEffect(() => {
    if (!activeChat || !user?.id) return;

    if (observerRef.current) observerRef.current.disconnect();
    sentReadIdsRef.current.clear();

    const socket = getSocket();
    if (!socket) return;

    const observer = new IntersectionObserver(
      (entries) => {
        let highestSequenceId = -1;
        let highestMsgId = '';
        const newlyReadIds: string[] = [];

        entries.forEach((entry) => {
          if (entry.isIntersecting) {
            const msgId = entry.target.getAttribute('data-message-id');
            const seqIdAttr = entry.target.getAttribute('data-sequence-id');
            if (msgId && seqIdAttr && !sentReadIdsRef.current.has(msgId)) {
              newlyReadIds.push(msgId);
              sentReadIdsRef.current.add(msgId);
              observer.unobserve(entry.target);

              const seqId = parseInt(seqIdAttr, 10);
              if (seqId > highestSequenceId) {
                highestSequenceId = seqId;
                highestMsgId = msgId;
              }
            }
          }
        });

        if (newlyReadIds.length > 0 && highestMsgId) {
          socket.emit('read_messages', {
            chatId: activeChat,
            lastReadMessageId: highestMsgId,
            lastReadSequenceId: highestSequenceId,
          });
          useChatStore.getState().markRead(activeChat, user.id, highestSequenceId);
        }
      },
      {
        root: scrollContainerRef.current,
        threshold: 0.1,
      }
    );

    observerRef.current = observer;

    const observeUnread = () => {
      if (!scrollContainerRef.current) return;
      const unreadElements = scrollContainerRef.current.querySelectorAll('.unread-detector');
      unreadElements.forEach((el: Element) => {
        const id = el.getAttribute('data-message-id');
        if (id && !sentReadIdsRef.current.has(id)) {
          observer.observe(el);
        }
      });
    };

    setTimeout(observeUnread, 100);
    return () => observer.disconnect();
  }, [activeChat, user?.id]);

  useEffect(() => {
    if (observerRef.current && scrollContainerRef.current) {
      const unreadElements = scrollContainerRef.current.querySelectorAll('.unread-detector');
      unreadElements.forEach((el: Element) => {
        const id = el.getAttribute('data-message-id');
        if (id && !sentReadIdsRef.current.has(id)) {
          observerRef.current?.observe(el);
        }
      });
    }
  }, [chatMessages, scrollReady]);

  useEffect(() => {
    if (scrollReady) {
      checkScrollPosition();
    }
  }, [chatMessages.length, scrollReady, checkScrollPosition]);

  const handleMouseMove = (e: React.MouseEvent<HTMLDivElement>) => {
    if (!chatViewRef.current) return;
    const { left, top } = chatViewRef.current.getBoundingClientRect();
    chatViewRef.current.style.setProperty('--mouse-x', `${e.clientX - left}px`);
    chatViewRef.current.style.setProperty('--mouse-y', `${e.clientY - top}px`);
  };

  // Поиск сообщений
  useEffect(() => {
    if (!searchText.trim() || !activeChat) {
      setSearchResults([]);
      return;
    }
    const timer = setTimeout(async () => {
      try {
        const results = await ChatApi.searchMessages(searchText, activeChat);
        setSearchResults(results);
      } catch (e) {
        console.error(e);
      }
    }, 300);
    return () => clearTimeout(timer);
  }, [searchText, activeChat]);

  const openSearch = () => {
    setShowSearch(true);
    setShowTopMenu(false);
    setTimeout(() => searchInputRef.current?.focus(), 100);
  };

  if (!activeChat || !chat) {
    return (
      <section className="flex-1 h-full flex flex-col items-center justify-center bg-[#010101] relative overflow-hidden">
        {/* Background Knot Texture */}
        <div className="absolute inset-0 opacity-[0.04] pointer-events-none flex items-center justify-center">
          <span className="material-symbols-outlined text-white text-[500px] select-none">cloud_download</span>
        </div>

        {/* Chat Empty State View */}
        <div className="flex-1 flex flex-col items-center justify-center z-10 p-12 text-center relative">
          <motion.div
            initial={{ scale: 0.8, opacity: 0 }}
            animate={{ scale: 1, opacity: 1 }}
            transition={{ duration: 0.8, ease: [0.16, 1, 0.3, 1] }}
            className="w-24 h-24 mb-6 rounded-[2rem] bg-[#1c1c1c] flex items-center justify-center shadow-[0_0_80px_rgba(48,150,229,0.15)] border border-white/5"
          >
            <span className="material-symbols-outlined text-[#3096e5] text-5xl select-none" style={{ fontVariationSettings: "'FILL' 1, 'wght' 400, 'GRAD' 0, 'opsz' 48" }}>
              forum
            </span>
          </motion.div>

          <h2 className="text-3xl font-black text-[#e5e2e1] tracking-tight mb-2 leading-tight">
            {t('selectChatTitle')}
          </h2>

          <p className="text-sm font-medium text-[#c1c6d7] max-w-sm leading-relaxed opacity-40 px-4">
            {t('selectChatSubtext')}
          </p>

          <motion.button
            initial={{ y: 20, opacity: 0 }}
            animate={{ y: 0, opacity: 1 }}
            transition={{ delay: 0.2 }}
            onClick={() => window.dispatchEvent(new CustomEvent('OPEN_NEW_CHAT'))}
            className="mt-10 px-9 py-3.5 bg-gradient-to-tr from-[#3096e5] to-[#9acbff] text-black font-extrabold text-base rounded-full shadow-[0_15px_40px_rgba(48,150,229,0.2)] hover:scale-105 active:scale-95 transition-all flex items-center gap-2.5"
          >
            <span className="material-symbols-outlined text-black font-bold text-xl">edit</span>
            {t('newMessage')}
          </motion.button>
        </div>
      </section>
    );
  }

  const handleToggleSelect = (msgId: string) => {
    const newMap = new Set(selectedMessages);
    if (newMap.has(msgId)) {
      newMap.delete(msgId);
      if (newMap.size === 0) setSelectionMode(false);
    } else {
      newMap.add(msgId);
    }
    setSelectedMessages(newMap);
  };

  const handleStartSelection = (msgId: string) => {
    setSelectionMode(true);
    setSelectedMessages(new Set([msgId]));
  };

  const handleForward = (targetChatId: string) => {
    const socket = getSocket();
    if (!socket || !activeChat) return;

    const messagesToForward = Array.from(selectedMessages)
      .map(id => chatMessages.find(m => m.id === id))
      .filter(Boolean)
      .sort((a, b) => new Date(a!.createdAt).getTime() - new Date(b!.createdAt).getTime());

    messagesToForward.forEach(msg => {
      socket.emit('send_message', {
        chatId: targetChatId,
        content: msg?.content,
        type: msg?.type,
        forwardedFromId: msg?.forwardedFromId || msg?.sender.id,
        attachments: msg?.media?.map(m => ({
          type: m.type,
          url: m.url,
          fileName: m.filename,
          fileSize: m.size
        })) || [],
      });
    });

    setSelectionMode(false);
    setSelectedMessages(new Set());
    setShowForwardModal(false);
    setActiveChat(targetChatId);
    useChatStore.getState().loadMessages(targetChatId);
  };

  const handleBulkDelete = (deleteForAll: boolean) => {
    const socket = getSocket();
    if (!socket || !activeChat) return;

    const ids = Array.from(selectedMessages);
    socket.emit('delete_messages', {
      messageIds: ids,
      chatId: activeChat,
      deleteForAll,
    });

    // Optimistic local removal
    if (!deleteForAll) {
      useChatStore.getState().hideMessages(ids, activeChat);
    }

    setSelectionMode(false);
    setSelectedMessages(new Set());
    setShowDeleteMenu(false);
  };

  return (
    <div
      ref={chatViewRef}
      onMouseMove={handleMouseMove}
      className={`flex-1 flex flex-col h-full overflow-hidden bg-surface-container-lowest relative z-0 chat-theme-${chatTheme} transition-colors duration-500`}
    >
      <div className="absolute inset-0 pointer-events-none bg-gradient-to-b from-primary/5 to-transparent h-32 opacity-30" />
      {selectionMode ? (
        <div className="h-[76px] flex items-center justify-between px-6 bg-surface-container-highest/80 backdrop-blur-xl z-20 flex-shrink-0 animate-in slide-in-from-top-2 border-none">
          <div className="flex items-center gap-4 text-on-surface">
            <button onClick={() => { setSelectionMode(false); setSelectedMessages(new Set()); }} className="p-2 -ml-2 rounded-xl hover:bg-on-surface/10 transition slide-on-ice">
              <span className="material-symbols-outlined">close</span>
            </button>
            <span className="text-lg font-bold font-headline">{selectedMessages.size} {t('selected')}</span>
          </div>
          <div className="flex items-center gap-3">
            <div className="relative" ref={deleteMenuRef}>
              <button
                disabled={selectedMessages.size === 0}
                onClick={() => isFavorites ? handleBulkDelete(false) : setShowDeleteMenu(!showDeleteMenu)}
                className="flex items-center gap-2 px-4 py-2 bg-red-500/90 text-white font-medium rounded-xl hover:bg-red-600 transition-colors disabled:opacity-50"
              >
                <Trash2 size={18} />
                {t('delete')}
              </button>
              <AnimatePresence>
                {showDeleteMenu && (
                  <motion.div
                    initial={{ opacity: 0, scale: 0.95, y: -5 }}
                    animate={{ opacity: 1, scale: 1, y: 0 }}
                    exit={{ opacity: 0, scale: 0.95, y: -5 }}
                    transition={{ duration: 0.15 }}
                    className="absolute right-0 top-full mt-2 w-56 rounded-2xl bg-[#1a1a1a] shadow-[0_20px_50px_rgba(0,0,0,0.5)] z-50 py-1.5 ring-1 ring-white/10 overflow-hidden"
                  >
                    <button
                      onClick={() => handleBulkDelete(false)}
                      className="flex items-center gap-3 w-full px-4 py-3 text-sm text-zinc-300 hover:bg-surface-hover hover:text-white transition-colors"
                    >
                      <Trash2 size={16} className="text-zinc-400" />
                      {t('deleteForMe')}
                    </button>
                    <div className="border-t border-border/30 mx-3" />
                    <button
                      onClick={() => handleBulkDelete(true)}
                      className="flex items-center gap-3 w-full px-4 py-3 text-sm text-red-400 hover:bg-red-500/10 hover:text-red-300 transition-colors"
                    >
                      <Trash2 size={16} className="text-red-400" />
                      {t('deleteForAll')}
                    </button>
                  </motion.div>
                )}
              </AnimatePresence>
            </div>
            <button
              disabled={selectedMessages.size === 0}
              onClick={() => setShowForwardModal(true)}
              className="flex items-center gap-2 px-4 py-2 bg-white text-black font-medium rounded-xl hover:bg-zinc-200 transition-colors disabled:opacity-50"
            >
              <Forward size={18} />
              {t('forward')}
            </button>
          </div>
        </div>
      ) : (
        <div className="h-[76px] flex items-center justify-between px-6 bg-surface-container-lowest/40 backdrop-blur-xl z-20 flex-shrink-0 gap-2 border-none">
          <div className="flex items-center gap-2 min-w-0 flex-1">
            <button
              onClick={() => setActiveChat(null)}
              className="lg:hidden p-2 -ml-1 rounded-xl hover:bg-surface-container-highest/30 text-on-surface-variant transition-colors"
            >
              <span className="material-symbols-outlined">arrow_back</span>
            </button>
            <div
              className="flex items-center gap-4 min-w-0 flex-1 group cursor-pointer"
              onClick={() => {
                if (chat.type === 'personal' && otherMember) {
                  setProfileUserId(otherMember.user.id);
                } else if (chat.type === 'group') {
                  setShowGroupSettings(true);
                }
              }}
            >
              <div className="relative flex-shrink-0 transform transition-all duration-500 group-hover:scale-105 active:scale-95">
                {isFavorites ? (
                  <div className="w-11 h-11 rounded-2xl bg-gradient-to-br from-primary to-primary-container flex items-center justify-center shadow-lg shadow-primary/10 border-2 border-outline-variant/10">
                    <span className="material-symbols-outlined text-on-primary-container text-[20px]">bookmark</span>
                  </div>
                ) : (
                  <Avatar
                    src={chatAvatar}
                    name={chatName}
                    size="md"
                    online={isOnline ? true : undefined}
                    className="avatar-knot-container group-hover:border-primary/30"
                  />
                )}
              </div>
              <div className="min-w-0 text-left">
                <h3 className="text-lg font-bold font-headline text-on-surface truncate group-hover:text-primary transition-colors leading-none mb-1">{chatName}</h3>
                <p className="text-[11px] font-bold uppercase tracking-widest text-on-surface-variant/50">
                  {isFavorites
                    ? t('favoritesDescription')
                    : typingInChat.length > 0
                      ? <span className="text-primary font-black animate-pulse">{t('typing')}</span>
                      : isOnline
                        ? <span className="text-success">{t('online')}</span>
                        : chat.type === 'personal' && otherMember?.user.lastSeen
                          ? `${formatLastSeen(otherMember.user.lastSeen, lang)}`
                          : chat.type === 'group'
                            ? `${chat.members.length} ${t('members')}`
                            : ''}
                </p>
              </div>
            </div>
          </div>

          <div className="flex items-center gap-1.5 ml-4">
            <AnimatePresence>
              {showSearch && (
                <motion.div
                  initial={{ width: 0, opacity: 0 }}
                  animate={{ width: 200, opacity: 1 }}
                  exit={{ width: 0, opacity: 0 }}
                  className="overflow-hidden"
                >
                  <input
                    ref={searchInputRef}
                    type="text"
                    placeholder={t('searchMessages')}
                    value={searchText}
                    onChange={(e) => setSearchText(e.target.value)}
                    className="w-full px-4 py-2 rounded-xl bg-surface-container text-sm text-on-surface placeholder-on-surface-variant/30 border-none focus:ring-2 focus:ring-primary/20"
                  />
                </motion.div>
              )}
            </AnimatePresence>

            <button
              onClick={() => {
                if (showSearch) {
                  setShowSearch(false);
                  setSearchText('');
                  setSearchResults([]);
                } else {
                  openSearch();
                }
              }}
              className="hidden lg:flex p-2 rounded-xl hover:bg-surface-container-highest/40 transition-all duration-300 text-on-surface-variant hover:text-primary slide-on-ice"
            >
              {showSearch ? <span className="material-symbols-outlined">close</span> : <span className="material-symbols-outlined">search</span>}
            </button>

            {!isFavorites && config?.webRtc?.enabled && (
              <div className="hidden lg:flex items-center gap-1.5">
                <button
                  onClick={() => {
                    if (chat.type === 'personal' && otherMember) {
                      onStartCall?.(otherMember.user, 'voice');
                    } else if (chat.type === 'group') {
                      onStartGroupCall?.(chat.id, chat.name || 'Group', 'voice');
                    }
                  }}
                  className="p-2 rounded-xl hover:bg-surface-container-highest/40 transition-all duration-300 text-on-surface-variant hover:text-primary slide-on-ice" title={t('call')}>
                  <span className="material-symbols-outlined">call</span>
                </button>
                {config?.webRtc?.enableVideoCalls && (
                  <button
                    onClick={() => {
                      if (chat.type === 'personal' && otherMember) {
                        onStartCall?.(otherMember.user, 'video');
                      } else if (chat.type === 'group') {
                        onStartGroupCall?.(chat.id, chat.name || 'Group', 'video');
                      }
                    }}
                    className="p-2 rounded-xl hover:bg-surface-container-highest/40 transition-all duration-300 text-on-surface-variant hover:text-primary slide-on-ice" title={t('videoCall')}>
                    <span className="material-symbols-outlined">videocam</span>
                  </button>
                )}
              </div>
            )}

            <div className="relative" ref={topMenuRef}>
              <button
                onClick={() => setShowTopMenu(!showTopMenu)}
                className="p-2 rounded-xl hover:bg-surface-container-highest/40 transition-all duration-300 text-on-surface-variant hover:text-primary slide-on-ice"
              >
                <span className="material-symbols-outlined">more_vert</span>
              </button>
              <AnimatePresence>
                {showTopMenu && (
                  <motion.div
                    initial={{ opacity: 0, scale: 0.95, y: -5 }}
                    animate={{ opacity: 1, scale: 1, y: 0 }}
                    exit={{ opacity: 0, scale: 0.95, y: -5 }}
                    transition={{ duration: 0.15 }}
                    className="absolute right-0 top-full mt-2 w-56 rounded-2xl bg-[#1a1a1a] shadow-[0_20px_50px_rgba(0,0,0,0.5)] z-50 py-1.5 ring-1 ring-white/10"
                  >
                    <button
                      onClick={openSearch}
                      className="flex items-center gap-3 w-full px-4 py-2.5 text-sm text-zinc-300 hover:bg-surface-hover hover:text-white transition-colors"
                    >
                      <Search size={16} />
                      {t('searchMessages')}
                    </button>
                    {!isFavorites && config?.webRtc?.enabled && (
                      <>
                        <button
                          onClick={() => {
                            setShowTopMenu(false);
                            if (chat.type === 'personal' && otherMember) {
                              onStartCall?.(otherMember.user, 'voice');
                            } else if (chat.type === 'group') {
                              onStartGroupCall?.(chat.id, chat.name || 'Group', 'voice');
                            }
                          }}
                          className="lg:hidden flex items-center gap-3 w-full px-4 py-2.5 text-sm text-zinc-300 hover:bg-surface-hover hover:text-white transition-colors"
                        >
                          <Phone size={16} />
                          {t('call')}
                        </button>
                        {config?.webRtc?.enableVideoCalls && (
                          <button
                            onClick={() => {
                              setShowTopMenu(false);
                              if (chat.type === 'personal' && otherMember) {
                                onStartCall?.(otherMember.user, 'video');
                              } else if (chat.type === 'group') {
                                onStartGroupCall?.(chat.id, chat.name || 'Group', 'video');
                              }
                            }}
                            className="lg:hidden flex items-center gap-3 w-full px-4 py-2.5 text-sm text-zinc-300 hover:bg-surface-hover hover:text-white transition-colors"
                          >
                            <Video size={16} />
                            {t('videoCall')}
                          </button>
                        )}
                      </>
                    )}
                    {!isFavorites && chat.type === 'personal' && otherMember && (
                      <button
                        onClick={() => {
                          setShowTopMenu(false);
                          setProfileUserId(otherMember.user.id);
                        }}
                        className="flex items-center gap-3 w-full px-4 py-2.5 text-sm text-zinc-300 hover:bg-surface-hover hover:text-white transition-colors"
                      >
                        <UserPlus size={16} />
                        {t('userProfile')}
                      </button>
                    )}
                    {!isFavorites && (
                      <button
                        onClick={() => {
                          if (activeChat) {
                            const nowMuted = toggleMuteChat(activeChat);
                            setMuted(nowMuted);
                          }
                        }}
                        className="flex items-center gap-3 w-full px-4 py-2.5 text-sm text-zinc-300 hover:bg-surface-hover hover:text-white transition-colors"
                      >
                        {muted ? <Bell size={16} /> : <BellOff size={16} />}
                        {muted ? t('enableSound') : t('disableSound')}
                      </button>
                    )}
                    {!isFavorites && chat.type === 'group' && (
                      <button
                        onClick={() => {
                          setShowTopMenu(false);
                          setShowGroupSettings(true);
                        }}
                        className="flex items-center gap-3 w-full px-4 py-2.5 text-sm text-zinc-300 hover:bg-surface-hover hover:text-white transition-colors"
                      >
                        <Settings size={16} />
                        {t('groupSettings')}
                      </button>
                    )}
                    <div className="border-t border-white/5 my-1" />
                    <button
                      onClick={() => {
                        setShowTopMenu(false);
                        if (activeChat) {
                          setConfirmAction({
                            message: isFavorites ? t('clearHistoryConfirm') : t('clearChatConfirm'),
                            action: async () => {
                              try {
                                await ChatApi.clearChat(activeChat);
                                useChatStore.getState().clearMessages(activeChat);
                                const NotificationStore = await import('../../../../core/application/stores/notificationStore');
                                NotificationStore.useNotificationStore.getState().addNotification('success', t('chatCleared'));
                              } catch (e) {
                                console.error(e);
                              }
                            },
                          });
                        }
                      }}
                      className="flex items-center gap-3 w-full px-4 py-2.5 text-sm text-zinc-300 hover:bg-surface-hover hover:text-white transition-colors"
                    >
                      <Eraser size={16} />
                      {isFavorites ? t('clearHistory') : t('clearChat')}
                    </button>
                    {!isFavorites && (
                      <button
                        onClick={() => {
                          setShowTopMenu(false);
                          if (activeChat) {
                            setConfirmAction({
                              message: t('deleteChatConfirm'),
                              action: async () => {
                                try {
                                  await ChatApi.deleteChat(activeChat);
                                  useChatStore.getState().removeChat(activeChat);
                                } catch (e) {
                                  console.error(e);
                                }
                              },
                            });
                          }
                        }}
                        className="flex items-center gap-3 w-full px-4 py-2.5 text-sm text-red-400 hover:bg-red-500/10 transition-colors"
                      >
                        <Trash2 size={16} />
                        {t('deleteChat')}
                      </button>
                    )}
                  </motion.div>
                )}
              </AnimatePresence>
            </div>
          </div>
        </div>
      )}

      {/* Результаты поиска */}
      <AnimatePresence>
        {showSearch && searchResults.length > 0 && (
          <motion.div
            initial={{ height: 0, opacity: 0 }}
            animate={{ height: 'auto', opacity: 1 }}
            exit={{ height: 0, opacity: 0 }}
            className="absolute top-14 left-0 right-0 z-20 max-h-60 overflow-y-auto glass-strong border-b border-border"
          >
            {searchResults.map((msg) => (
              <div
                key={msg.id}
                className="px-4 py-2 hover:bg-surface-hover cursor-pointer border-b border-border/50 last:border-0"
                onClick={() => {
                  // Scroll to message
                  const el = document.getElementById(`msg-${msg.id}`);
                  if (el) {
                    el.scrollIntoView({ behavior: 'smooth', block: 'center' });
                    el.classList.add('highlight-message');
                    setTimeout(() => el.classList.remove('highlight-message'), 5000);
                  }
                  setShowSearch(false);
                  setSearchText('');
                  setSearchResults([]);
                }}
              >
                <div className="flex items-center gap-2 mb-0.5">
                  <span className="text-xs font-medium text-knot-400">
                    {msg.sender?.displayName || msg.sender?.username}
                  </span>
                  <span className="text-xs text-zinc-600">
                    {new Date(msg.createdAt).toLocaleDateString(lang === 'ru' ? 'ru' : 'en')}
                  </span>
                </div>
                <p className="text-sm text-zinc-300 truncate">{msg.content}</p>
              </div>
            ))}
          </motion.div>
        )}
      </AnimatePresence>

      {chat.isImporting ? (
        <div className="flex-1 flex flex-col items-center justify-center p-12 text-center bg-surface-container-lowest relative overflow-hidden">
          <div className="absolute inset-0 opacity-[0.02] pointer-events-none flex items-center justify-center">
            <span className="material-symbols-outlined text-white text-[500px] select-none">cloud_download</span>
          </div>

          <motion.div
            initial={{ scale: 0.9, opacity: 0, y: 20 }}
            animate={{ scale: 1, opacity: 1, y: 0 }}
            className="z-10 w-full max-w-md p-8 rounded-[2.5rem] bg-surface-container-low border border-outline/10 shadow-2xl backdrop-blur-3xl"
          >
            <div className="w-20 h-20 mx-auto mb-6 rounded-3xl bg-primary/10 flex items-center justify-center shadow-lg shadow-primary/5">
              <span className="material-symbols-outlined text-primary text-4xl animate-bounce">downloading</span>
            </div>

            <h2 className="text-2xl font-black text-on-surface tracking-tight mb-2">
              Идет импорт истории
            </h2>
            <p className="text-on-surface-variant text-sm font-medium mb-8 opacity-60 leading-relaxed">
              Мы переносим ваши сообщения и медиафайлы из Telegram. Это займет некоторое время.
            </p>

            <div className="space-y-4">
              <div className="flex items-center justify-between mb-2 px-1">
                <span className="text-xs font-black uppercase tracking-widest text-primary">
                  {importStatus?.status === 'Processing' ? 'Обработка' :
                    importStatus?.status === 'Queued' ? 'В очереди' : 'Загрузка'}
                </span>
                <span className="text-xs font-black text-on-surface tabular-nums">
                  {importStatus?.processed || 0} / {importStatus?.total || 0}
                </span>
              </div>

              <div className="h-3 w-full bg-surface-container-highest rounded-full overflow-hidden border border-outline/10 p-0.5">
                <motion.div
                  initial={{ width: 0 }}
                  animate={{ width: `${Math.min(100, Math.round(((importStatus?.processed || 0) / (importStatus?.total || 1)) * 100))}%` }}
                  transition={{ type: 'spring', damping: 20 }}
                  className="h-full bg-linear-to-r from-primary to-primary-container rounded-full shadow-[0_0_20px_rgba(48,150,229,0.3)] transition-all duration-300"
                />
              </div>

              <p className="text-[11px] font-bold text-on-surface-variant/40 uppercase tracking-[0.2em] pt-4">
                Чат станет доступен автоматически
              </p>
            </div>
          </motion.div>
        </div>
      ) : (
        <>
          {chat?.type === 'group' && config?.webRtc?.enabled && activeGroupCallParticipants.length > 0 && (
            <button
              onClick={() => onStartGroupCall?.(chat.id, chat.name || 'Group', 'voice')}
              className="flex items-center gap-3 px-4 py-2.5 border-b border-outline/10 bg-emerald-500/10 hover:bg-emerald-500/20 transition-colors text-left w-full flex-shrink-0"
            >
              <div className="w-8 h-8 rounded-full bg-emerald-500/20 flex items-center justify-center">
                <Phone size={14} className="text-emerald-400" />
              </div>
              <div className="min-w-0 flex-1">
                <p className="text-xs font-medium text-emerald-400">{t('activeCall')}</p>
                <p className="text-sm text-zinc-300">{activeGroupCallParticipants.length} {t('participants')}</p>
              </div>
              <span className="text-xs text-emerald-400 font-medium px-3 py-1 rounded-full bg-emerald-500/20">{t('joinCall')}</span>
            </button>
          )}

          {chatPinnedMessages.length > 0 && (
            <div className="flex-shrink-0 flex items-center gap-0 border-b border-outline/10 bg-surface-container-high/60 hover:bg-surface-container-high transition-colors overflow-hidden h-[54px] relative">
              {/* Cycling progress indicator for multiple pins */}
              {chatPinnedMessages.length > 1 && (
                <div className="absolute left-1 top-1.5 bottom-1.5 w-0.5 rounded-full bg-white/5 flex flex-col gap-0.5 overflow-hidden">
                  {chatPinnedMessages.map((_, idx) => (
                    <div
                      key={idx}
                      className={`flex-1 transition-colors duration-300 ${idx === pinnedIndex % chatPinnedMessages.length ? 'bg-primary' : 'bg-primary/20'}`}
                    />
                  ))}
                </div>
              )}

              <button
                onClick={() => {
                  const currentPin = chatPinnedMessages[pinnedIndex % chatPinnedMessages.length];
                  if (!currentPin) return;
                  handleJumpToMessage(currentPin.id, currentPin.sequenceId);
                  if (chatPinnedMessages.length > 1) {
                    setPinnedIndex(prev => (prev + 1) % chatPinnedMessages.length);
                  }
                }}
                className={`flex-1 flex items-center gap-3 px-4 py-2 text-left h-full ${chatPinnedMessages.length > 1 ? 'ml-1.5' : ''}`}
              >
                <div className="w-8 h-8 rounded-full bg-primary/10 flex items-center justify-center flex-shrink-0">
                  <Pin size={14} className="text-primary rotate-45" />
                </div>
                <div className="min-w-0 flex-1">
                  <p className="text-[11px] font-black text-primary uppercase tracking-wider">
                    {t('pinnedMessage')} {chatPinnedMessages.length > 1 ? `#${(pinnedIndex % chatPinnedMessages.length) + 1}` : ''}
                  </p>
                  <p className="text-sm text-zinc-300 truncate font-medium">
                    {chatPinnedMessages[pinnedIndex % chatPinnedMessages.length]?.content ||
                      (chatPinnedMessages[pinnedIndex % chatPinnedMessages.length]?.media?.length > 0 ? t('media') : '...')}
                  </p>
                </div>
              </button>

              <div className="flex items-center px-2">
                <button
                  onClick={(e) => {
                    e.stopPropagation();
                    const socket = getSocket();
                    const currentPin = chatPinnedMessages[pinnedIndex % chatPinnedMessages.length];
                    if (socket && activeChat && currentPin) {
                      socket.emit('unpin_message', { messageId: currentPin.id, chatId: activeChat });
                    }
                  }}
                  className="w-8 h-8 rounded-full flex items-center justify-center text-zinc-500 hover:text-white hover:bg-white/5 transition-all"
                  title={t('unpin' as any) || 'Открепить'}
                >
                  <X size={16} />
                </button>
              </div>
            </div>
          )}

          <div className="relative flex-1 flex flex-col overflow-hidden">
            <AnimatePresence mode="wait">
              {showStickyDate && stickyDate && (
                <motion.div
                  initial={{ opacity: 0, scale: 0.9, y: -20 }}
                  animate={{ opacity: 1, scale: 1, y: 0 }}
                  exit={{ opacity: 0, scale: 0.9, y: -20 }}
                  transition={{ type: 'spring', damping: 25, stiffness: 300 }}
                  key="sticky-date"
                  className="absolute top-6 left-1/2 -translate-x-1/2 z-[999] pointer-events-none"
                >
                  <span className="px-4 py-1.5 rounded-full text-[11px] font-black uppercase tracking-widest text-white bg-black/60 backdrop-blur-xl shadow-[0_10px_30px_rgba(0,0,0,0.5)] border border-white/10 ring-2 ring-black/20 whitespace-nowrap">
                    {stickyDate}
                  </span>
                </motion.div>
              )}
            </AnimatePresence>

            <div
              ref={scrollContainerRef}
              onScroll={handleScroll}
              className={`flex-1 overflow-y-auto overflow-x-hidden px-6 pt-6 pb-2 relative z-10 scroll-smooth-container ${!scrollReady && !isLoadingMessages && chatMessages.length > 0 ? 'invisible' : ''}`}
            >
              {isLoadingMessages && chatMessages.length === 0 ? (
                <div className="flex justify-center py-8">
                  <div className="w-6 h-6 border-2 border-primary border-t-transparent rounded-full animate-spin" />
                </div>
              ) : chatMessages.length === 0 ? (
                <div className="flex items-center justify-center h-full">
                  <div className="flex flex-col items-center gap-4 opacity-30 select-none">
                    <MessagesSquare size={64} className="text-on-surface-variant" />
                    <p className="text-sm font-bold uppercase tracking-widest text-on-surface-variant">{t('noMessages')}</p>
                  </div>
                </div>
              ) : (
                <div className="space-y-1 max-w-3xl mx-auto">
                  {isLoadingMessages && (
                    <div className="flex justify-center py-4">
                      <div className="w-5 h-5 border-2 border-primary border-t-transparent rounded-full animate-spin" />
                    </div>
                  )}
                  {chatMessages.map((msg, i) => {
                    const prevMsg = i > 0 ? chatMessages[i - 1] : null;
                    const showAvatar = !prevMsg || prevMsg.senderId !== msg.senderId;
                    const showDate =
                      !prevMsg ||
                      new Date(msg.createdAt).toDateString() !== new Date(prevMsg.createdAt).toDateString();

                    const isFirstUnread = firstUnreadId === msg.id;

                    return (
                      <div
                        key={msg.id}
                        data-message-id={msg.id}
                        data-sequence-id={msg.sequenceId}
                        className={`transition-colors duration-500 ${msg.senderId !== user?.id && !msg.readBy?.some(r => r.userId === user?.id) ? 'unread-detector' : ''}`}
                      >
                        {isFirstUnread && (
                          <div id="unread-divider" className="flex items-center justify-center my-4 opacity-80 select-none">
                            <div className="flex-1 h-px bg-outline/20"></div>
                            <span className="px-4 text-[11px] font-semibold tracking-wider uppercase text-zinc-400">
                              {t('unreadMessages')}
                            </span>
                            <div className="flex-1 h-px bg-outline/20"></div>
                          </div>
                        )}
                        {showDate && (
                          <div className="flex justify-center my-4">
                            <span className="px-3 py-1 rounded-full text-xs text-zinc-400 glass-effect">
                              {new Date(msg.createdAt).toLocaleDateString(lang === 'ru' ? 'ru' : 'en', {
                                day: 'numeric',
                                month: 'long',
                              })}
                            </span>
                          </div>
                        )}
                        <MessageBubble
                          message={msg}
                          isMine={msg.senderId === user?.id}
                          showAvatar={showAvatar}
                          onViewProfile={(userId) => setProfileUserId(userId)}
                          selectionMode={selectionMode}
                          isSelected={selectedMessages.has(msg.id)}
                          onToggleSelect={handleToggleSelect}
                          onStartSelectionMode={handleStartSelection}
                          onForward={(id) => {
                            setSelectedMessages(new Set([id]));
                            setShowForwardModal(true);
                          }}
                        />
                      </div>
                    );
                  })}
                  <div ref={messagesEndRef} className="h-4" />
                </div>
              )}
            </div>

            <AnimatePresence>
              {showScrollDown && (
                <motion.button
                  initial={{ scale: 0.5, opacity: 0, y: 20 }}
                  animate={{ scale: 1, opacity: 1, y: 0 }}
                  exit={{ scale: 0.5, opacity: 0, y: 20 }}
                  whileHover={{ scale: 1.1 }}
                  whileTap={{ scale: 0.9 }}
                  onClick={() => scrollToBottom(true)}
                  className="absolute bottom-8 right-8 w-14 h-14 rounded-2xl bg-primary text-on-primary shadow-2xl flex items-center justify-center z-20 hover:shadow-primary/20 transition-all"
                >
                  <ArrowDown size={28} />
                  {unreadCount > 0 && (
                    <span className="absolute -top-2 -right-2 min-w-[24px] h-6 px-1.5 rounded-full bg-error text-on-error text-[12px] font-black flex items-center justify-center shadow-lg border-2 border-surface-container-lowest">
                      {unreadCount > 99 ? '99+' : unreadCount}
                    </span>
                  )}
                </motion.button>
              )}
            </AnimatePresence>
          </div>

          <footer className="flex-shrink-0 bg-surface-container-lowest/40 backdrop-blur-xl border-t border-white/5 safe-area-bottom relative z-50">
            <MessageInput chatId={activeChat} />
          </footer>
        </>
      )}

      {/* Typing indicator is already shown in the header, removed from here to prevent layout jumping */}

      {(() => {
        return (
          <>
            <AnimatePresence>
              {profileUserId && (
                <UserProfile
                  userId={profileUserId}
                  chatId={activeChat || undefined}
                  onClose={() => setProfileUserId(null)}
                  onGoToMessage={(msgId: any) => { handleJumpToMessage(msgId); setProfileUserId(null); }}
                  isSelf={profileUserId === user?.id}
                />
              )}
            </AnimatePresence>

            <AnimatePresence>
              {showGroupSettings && chat && chat.type === 'group' && (
                <GroupSettings
                  chat={chat}
                  onClose={() => setShowGroupSettings(false)}
                  onGoToMessage={(msgId) => { handleJumpToMessage(msgId); setShowGroupSettings(false); }}
                />
              )}
            </AnimatePresence>
          </>
        );
      })()}

      <AnimatePresence>
        {showForwardModal && (
          <ForwardModal
            onClose={() => setShowForwardModal(false)}
            onForward={handleForward}
          />
        )}
      </AnimatePresence>

      <ConfirmModal
        open={!!confirmAction}
        message={confirmAction?.message || ''}
        onConfirm={() => {
          confirmAction?.action();
          setConfirmAction(null);
        }}
        onCancel={() => setConfirmAction(null)}
      />
    </div>
  );
}
