<template>
  <div class="chat-view-container d-flex flex-column">
    <div v-if="loadingInitialMessages" class="flex-grow-1 d-flex justify-content-center align-items-center">
      <div class="spinner-border text-primary" role="status">
        <span class="visually-hidden">Загрузка сообщений...</span>
      </div>
    </div>
    <div v-if="error" class="alert alert-danger m-3">{{ error }}</div>

    <div v-if="!loadingInitialMessages && !conversationData" class="alert alert-warning m-3">
      Не удалось загрузить данные диалога.
    </div>

    <div v-if="conversationData && !loadingInitialMessages" class="chat-header p-3 bg-light border-bottom">
      <h5 class="mb-0">Чат с {{ getOtherParticipantName() || 'Собеседник' }}</h5>
    </div>

    <div ref="messagesContainer" class="messages-area flex-grow-1 p-3" style="overflow-y: auto;">
      <template v-for="item in messagesWithDateSeparators" :key="item.id">
        <div v-if="item.type === 'date_separator'" class="date-separator text-center my-2">
          <span class="badge bg-secondary-subtle text-dark-emphasis">{{ formatDateHeader(item.timestamp) }}</span>
        </div>
        <div v-else-if="item.type === 'message'"
             :class="['message-item-wrapper', item.data.sender?._id === currentUser?._id ? 'sent-wrapper' : 'received-wrapper']"
             @mouseenter="!isTouchDevice.value && handleMouseEnter(item.data)" 
             @mouseleave="!isTouchDevice.value && handleMouseLeave()"
             
        >
          <div :class="['message-bubble', item.data.sender?._id === currentUser?._id ? 'sent' : 'received']"
               @click.stop="handleMessageTap(item.data, $event)" 
               @contextmenu.stop="handleNativeContextMenu($event, item.data)">
            <div class="message-content">
              <p class="mb-0">{{ item.data.text }}</p>
              <small class="message-timestamp text-muted">
                {{ formatMessageTimestamp(item.data.createdAt) }}
                <span v-if="item.data.sender?._id === currentUser?._id && item.data.isSending" class="ms-1 fst-italic">(отправка...)</span>
                <span v-if="item.data.sender?._id === currentUser?._id && !item.data.isSending" class="ms-1">
                  <i :class="getMessageStatusIcon(item.data)"></i>
                </span>
              </small>
            </div>
          </div>
          <!-- Кнопка удаления для ПК (появляется при наведении) -->
          <button v-if="!isTouchDevice.value && hoveredMessageId === item.data._id && item.data.sender?._id === currentUser?._id"
                  @click="confirmDeleteMessage(item.data._id)"
                  class="btn btn-sm btn-danger delete-message-btn"
                  title="Удалить сообщение">
            <i class="bi bi-trash"></i>
          </button>
        </div>
      </template>
    </div>

    <!-- Контекстное меню для мобильных устройств -->
    <div v-if="contextMenu && contextMenu.visible"
         ref="contextMenuRef" 
         class="context-menu"
         :style="{ top: contextMenu.y + 'px', left: contextMenu.x + 'px' }">
      <ul>
        <li @click="confirmDeleteMessage(contextMenu.messageId)">
          <i class="bi bi-trash"></i>
          <span>Удалить сообщение</span>
        </li>
      </ul>
    </div>

    <!-- Индикатор "печатает" -->
    <div v-if="otherUserIsTyping" class="typing-indicator px-3 pb-2 text-muted fst-italic">
      {{ getOtherParticipantName() || 'Собеседник' }} печатает...
    </div>

    <div v-if="isAuthenticated" class="message-input-area p-3 border-top bg-light">
      <form @submit.prevent="sendMessage" class="d-flex">
        <input
          type="text"
          v-model="newMessageText"
          class="form-control me-2"
          placeholder="Введите сообщение..."
          :disabled="sendingMessage"
        />
        <button type="submit" class="btn btn-primary" :disabled="sendingMessage || !newMessageText.trim()">
          <span v-if="sendingMessage" class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span>
          Отправить
        </button>
      </form>
    </div>
  </div>
</template>

<script setup>
import { ref, onMounted, onUnmounted, nextTick, computed, watch } from 'vue';
import { useRoute } from 'vue-router';
import api from '@/services/api';
import { useAuth } from '@/auth';
import { getSocket, connectSocket, disconnectSocket } from '@/services/socketService';

const route = useRoute();
const { user: currentUser, isAuthenticated } = useAuth();

const isTouchDevice = ref(false);
const hoveredMessageId = ref(null);
const contextMenu = ref({ visible: false, x: 0, y: 0, messageId: null });
const contextMenuRef = ref(null); 

const handleMouseEnter = (message) => {
  if (!isTouchDevice.value) {
    hoveredMessageId.value = message._id;
  }
};

const handleMouseLeave = () => {
  if (!isTouchDevice.value) {
    hoveredMessageId.value = null;
  }
};

// New handler for tap/click
const handleMessageTap = (message, event) => {
  if (message.sender?._id === currentUser.value?._id) {
    // event.preventDefault(); // Already handled by contextmenu or default click behavior if not a link
    // event.stopPropagation(); // Handled by .stop modifier in template
    showContextMenu(message, event);
  }
  // For messages from other users, allow default behavior (e.g., text selection, link clicks)
};

const showContextMenu = (message, eventSource) => {
  if (message.sender?._id === currentUser.value?._id) {
    contextMenu.value.messageId = message._id;
    let x = eventSource.clientX;
    let y = eventSource.clientY;

    // Set initial position and make visible to calculate dimensions
    contextMenu.value.x = x;
    contextMenu.value.y = y;
    contextMenu.value.visible = true;

    nextTick(() => {
      if (contextMenuRef.value) {
        const menuWidth = contextMenuRef.value.offsetWidth;
        const menuHeight = contextMenuRef.value.offsetHeight;
        const screenWidth = window.innerWidth;
        const screenHeight = window.innerHeight;
        const PADDING = 10; // Screen edge padding

        if (x + menuWidth > screenWidth - PADDING) {
          x = screenWidth - menuWidth - PADDING;
        }
        if (x < PADDING) {
          x = PADDING;
        }

        if (y + menuHeight > screenHeight - PADDING) {
          y = screenHeight - menuHeight - PADDING;
        }
        if (y < PADDING) {
          y = PADDING;
        }
        
        contextMenu.value.x = x;
        contextMenu.value.y = y;
      }
    });
  } else {
    contextMenu.value.visible = false;
  }
};

const conversationId = ref(route.params.conversationId);
const conversationData = ref(null); // Для информации о диалоге (например, участники)
const messages = ref([]);
const newMessageText = ref('');

const loadingInitialMessages = ref(true);
const sendingMessage = ref(false);
const error = ref('');

let socket = null;
const otherUserIsTyping = ref(false); // Для отображения индикатора, что собеседник печатает
let stopTypingEmitTimer = null; // Новое имя таймера для отправки stopTyping
const userHasSentTypingEvent = ref(false); // Отслеживает, отправляли ли 'typing' для текущей сессии набора
const TYPING_TIMER_LENGTH = 1500; // мс, через сколько отправлять stopTyping

const messagesWithDateSeparators = computed(() => {
  if (!messages.value || messages.value.length === 0) return [];

  const result = [];
  let lastDate = null;

  messages.value.forEach(message => {
    const messageTimestamp = message.createdAt || Date.now(); // Fallback for temp messages if needed
    const messageDate = new Date(messageTimestamp).toDateString();
    if (messageDate !== lastDate) {
      result.push({ type: 'date_separator', timestamp: messageTimestamp, id: `date-${messageTimestamp}-${message._id || Math.random()}` });
      lastDate = messageDate;
    }
    result.push({ type: 'message', data: message, id: message._id || message.tempId || `msg-${Math.random()}` });
  });
  return result;
});

const formatDateHeader = (timestamp) => {
  if (!timestamp) return '';
  const date = new Date(timestamp);
  const today = new Date();
  const yesterday = new Date(today);
  yesterday.setDate(yesterday.getDate() - 1);

  if (date.toDateString() === today.toDateString()) {
    return 'Сегодня';
  } else if (date.toDateString() === yesterday.toDateString()) {
    return 'Вчера';
  } else {
    return date.toLocaleDateString([], { day: 'numeric', month: 'long', year: 'numeric' });
  }
};

// Функция для отметки сообщений как прочитанных
const markMessagesAsReadOnServer = () => {
  if (socket && conversationId.value && currentUser.value?._id) {
    // Проверим, есть ли вообще непрочитанные сообщения от собеседника
    const unreadMessagesFromOther = messages.value.some(
      msg => msg.sender?._id !== currentUser.value._id &&
             (!msg.readBy || !msg.readBy.includes(currentUser.value._id))
    );

    if (unreadMessagesFromOther) {
      console.log('[ChatView] Отправка события markMessagesAsRead для диалога:', conversationId.value);
      socket.emit('markMessagesAsRead', {
        conversationId: conversationId.value,
        userId: currentUser.value._id,
      });
    }
  }
};

// Функция для прокрутки к последнему сообщению
const messagesContainer = ref(null);
const scrollToBottom = () => {
  nextTick(() => {
    if (messagesContainer.value) {
      messagesContainer.value.scrollTop = messagesContainer.value.scrollHeight;
    }
  });
};

const fetchInitialMessages = async () => {
  if (!conversationId.value) return;
  loadingInitialMessages.value = true;
  error.value = '';
  try {
    console.log(`[ChatView] Запрос истории сообщений для диалога: ${conversationId.value}`);
    const response = await api.getMessagesForConversation(conversationId.value);
    // Теперь API возвращает объект { conversation: {}, messages: [] }
    messages.value = response.data.messages || [];
    conversationData.value = response.data.conversation; // <--- СОХРАНЯЕМ ДАННЫЕ ДИАЛОГА
    
    console.log('[ChatView] Сообщения загружены:', messages.value);
    console.log('[ChatView] Данные диалога загружены:', conversationData.value); // Для отладки
    scrollToBottom();
    markMessagesAsReadOnServer(); // Отмечаем как прочитанные при загрузке
  } catch (err) {
    console.error('[ChatView] Ошибка загрузки сообщений:', err);
    error.value = err.response?.data?.message || 'Не удалось загрузить сообщения.';
  } finally {
    loadingInitialMessages.value = false;
  }
};

const getOtherParticipant = () => {
  if (conversationData.value && conversationData.value.participants && currentUser.value) {
    return conversationData.value.participants.find(p => p._id !== currentUser.value._id);
  }
  return null;
};
const getOtherParticipantName = () => getOtherParticipant()?.name;


const sendMessage = () => {
  if (!newMessageText.value.trim() || !socket || !currentUser.value || sendingMessage.value) return;
  
  const otherParticipant = getOtherParticipant(); // Нужно получить ID получателя!
  // Это слабое место, если conversationData не загружено правильно.
  // Для теста можно временно захардкодить receiverId, если знаешь его.
  // Или передать его из ChatListView.
  let receiverId; 
  // ВАЖНО: Логика получения receiverId должна быть надежной.
  // Например, если мы перешли из списка чатов, мы можем передать инфо о собеседнике.
  // Или при загрузке диалога, API должен вернуть участников.
  // Для примера, если бы conversationData было установлено:
  if (otherParticipant) {
      receiverId = otherParticipant._id;
  } else {
      console.error("Не удалось определить получателя!");
      error.value = "Не удалось определить получателя для отправки сообщения.";
      return;
  }

  const messageData = {
    senderId: currentUser.value._id,
    receiverId: receiverId, // ID получателя
    text: newMessageText.value,
    conversationId: conversationId.value, // Можно отправлять, если нужно на сервере
    // tempId: Date.now().toString() // Временный ID для оптимистичного обновления UI
  };

  // Оптимистичное добавление (можно улучшить, добавив статус isSending)
  // const tempMessage = { ...messageData, createdAt: new Date().toISOString(), sender: currentUser.value, tempId: messageData.tempId, isSending: true };
  // messages.value.push(tempMessage);
  // scrollToBottom();

  console.log('[ChatView] Отправка сообщения через сокет:', messageData);
  sendingMessage.value = true;
  socket.emit('sendMessage', messageData);
  
  // sendingMessage будет false, когда придет подтверждение или ошибка от сервера (пока не реализовано)
  // Пока просто сбросим через некоторое время или после получения своего же сообщения
  // setTimeout(() => { sendingMessage.value = false; }, 1000); 
  newMessageText.value = ''; // Очищаем поле ввода
};

const handleNewMessage = (message) => {
  console.log('[ChatView] Получено новое сообщение:', message);
  // Убедимся, что сообщение для текущего открытого диалога
  if (message.conversationId === conversationId.value) {
    messages.value.push(message); 
    scrollToBottom();

    // Если это сообщение от другого пользователя, и мы в фокусе, отмечаем как прочитанное
    if (message.sender?._id !== currentUser.value?._id && document.hasFocus()) {
      markMessagesAsReadOnServer();
    }
  }
  sendingMessage.value = false; 
};

const handleMessageDeletedBySocket = (data) => {
  console.log('[ChatView] Получено событие удаления сообщения от сокета:', data);
  const { messageId, conversationId: convId } = data;
  if (convId === conversationId.value) {
    messages.value = messages.value.filter(msg => msg._id !== messageId);
    // Дополнительно можно обновить UI, если это необходимо
    // Например, если удаленное сообщение было последним, или для обновления счетчиков
  }
};

const confirmDeleteMessage = (messageId) => {
  // Логика подтверждения удаления (например, показать модальное окно)
  // А затем, если пользователь подтвердил, вызвать deleteMessage
  console.log('Confirm delete messageId:', messageId);
  // Пока просто вызываем deleteMessage напрямую для примера
  deleteMessage(messageId);
};

const deleteMessage = async (messageId) => {
  try {
    // Оптимистичное удаление из UI
    messages.value = messages.value.filter(msg => msg._id !== messageId);
    // Отправка запроса на сервер
    // ВАЖНО: Убедитесь, что conversationId.value передается в api.deleteMessage
    await api.deleteMessage(conversationId.value, messageId); 
    console.log(`[ChatView] Сообщение ${messageId} удалено локально и на сервере.`);
    // Сокет событие messageDeleted должно прийти от сервера и подтвердить удаление
    // или обработать его для других клиентов. Если вы не хотите дублирования,
    // можно не удалять из messages.value здесь, а дождаться события от сокета.
    // Однако, оптимистичное удаление улучшает UX.

    // Закрыть контекстное меню, если оно было открыто для этого сообщения
    if (contextMenu.value && contextMenu.value.messageId === messageId) {
      contextMenu.value.visible = false;
    }

  } catch (err) {
    console.error(`[ChatView] Ошибка удаления сообщения ${messageId}:`, err);
    error.value = err.response?.data?.message || 'Не удалось удалить сообщение.';
    // Возможно, стоит вернуть сообщение в список, если удаление на сервере не удалось
    // fetchInitialMessages(); // или более тонкое обновление
  }
};

// Обработка события, что наши сообщения прочитаны собеседником
const handleMessagesReadByOther = ({ conversationId: readConversationId, readerId }) => {
  if (readConversationId === conversationId.value) {
    console.log(`[ChatView] Сообщения в диалоге ${readConversationId} прочитаны пользователем ${readerId}`);
    // Обновляем статус сообщений, отправленных текущим пользователем
    messages.value = messages.value.map(msg => {
      if (msg.sender?._id === currentUser.value?._id) {
        // Если сообщение отправлено нами и еще не имеет этого readerId в readBy
        // (на случай если readBy не пришло сразу с сообщением или было обновлено)
        // Это упрощенный вариант. В идеале, сервер должен присылать обновленные сообщения.
        // Но для отображения галочек, достаточно знать, что ОДИН получатель (собеседник) прочитал.
        // Мы просто добавляем readerId в readBy для наших сообщений, если его там нет.
        const updatedReadBy = msg.readBy ? [...msg.readBy] : [];
        if (!updatedReadBy.includes(readerId)) {
          updatedReadBy.push(readerId);
        }
        return { ...msg, readBy: updatedReadBy };
      }
      return msg;
    });
  }
};

// Следим за видимостью вкладки для отметки сообщений как прочитанных
const handleVisibilityChange = () => {
  if (document.visibilityState === 'visible') {
    markMessagesAsReadOnServer();
  }
};

watch(newMessageText, (newValue /*, oldValue */) => { // oldValue больше не используется напрямую для этой логики
  if (!socket || !isAuthenticated.value || !conversationData.value || !currentUser.value) return;

  const otherParticipant = getOtherParticipant();
  if (!otherParticipant?._id) {
    console.warn("[ChatView] Не удалось определить собеседника для событий печати.");
    return;
  }
  const receiverId = otherParticipant._id;

  const payload = {
    conversationId: conversationId.value,
    receiverId: receiverId,
    senderId: currentUser.value._id
  };

  // Всегда очищаем таймер stopTyping при любом изменении текста
  clearTimeout(stopTypingEmitTimer);

  if (newValue.trim().length > 0) {
    // Пользователь печатает (поле не пустое)
    if (!userHasSentTypingEvent.value) {
      // Если событие 'typing' еще не было отправлено для этой "серии" набора
      if (socket.connected) { // Убедимся, что сокет все еще подключен
        socket.emit('typing', payload);
        userHasSentTypingEvent.value = true;
        console.log('[ChatView] Emit typing (new burst)');
      }
    }

    // Устанавливаем таймер для отправки 'stopTyping', если пользователь перестанет печатать
    stopTypingEmitTimer = setTimeout(() => {
      if (socket.connected) { // Убедимся, что сокет все еще подключен
        socket.emit('stopTyping', payload);
        userHasSentTypingEvent.value = false; // Сбрасываем для следующей "серии" набора
        console.log('[ChatView] Emit stopTyping (timeout)');
      }
    }, TYPING_TIMER_LENGTH);

  } else {
    // Пользователь очистил поле ввода или оно стало пустым
    if (userHasSentTypingEvent.value) {
      // Если событие 'typing' было активно, отправляем 'stopTyping'
      if (socket.connected) { // Убедимся, что сокет все еще подключен
        socket.emit('stopTyping', payload);
        userHasSentTypingEvent.value = false;
        console.log('[ChatView] Emit stopTyping (cleared input)');
      }
    }
  }
});


onMounted(async () => {
  isTouchDevice.value = ('ontouchstart' in window) || (navigator.maxTouchPoints > 0);
  if (!isAuthenticated.value) {
    // router.push('/login'); // Оставил закомментированным, т.к. в оригинале так
    return;
  }
  await fetchInitialMessages(); 

  socket = getSocket(); 
  if (!socket) {
    socket = connectSocket(); 
  }

  if (socket) {
    socket.on('getMessage', handleNewMessage);
    socket.on('messagesRead', handleMessagesReadByOther);
    socket.on('userTyping', ({ conversationId: incomingConvId, senderId }) => {
      const otherP = getOtherParticipant();
      if (incomingConvId === conversationId.value && otherP && senderId === otherP._id) {
        otherUserIsTyping.value = true;
      }
    });
    socket.on('userStopTyping', ({ conversationId: incomingConvId, senderId }) => {
      const otherP = getOtherParticipant();
      if (incomingConvId === conversationId.value && otherP && senderId === otherP._id) {
        otherUserIsTyping.value = false;
      }
    });
    socket.on('messageDeleted', handleMessageDeletedBySocket);
    
    if (conversationId.value) {
      socket.emit('joinConversationRoom', conversationId.value);
    }

    markMessagesAsReadOnServer();
    document.addEventListener('visibilitychange', handleVisibilityChange);
    window.addEventListener('focus', markMessagesAsReadOnServer);
    document.addEventListener('click', handleClickOutsideContextMenu, true);
  }
});

onUnmounted(() => {
  if (socket) {
    socket.off('getMessage', handleNewMessage);
    socket.off('messagesRead', handleMessagesReadByOther);
    socket.off('userTyping');
    socket.off('userStopTyping');
    socket.off('messageDeleted', handleMessageDeletedBySocket);

    if (conversationId.value) {
      socket.emit('leaveConversationRoom', conversationId.value);
    }

    document.removeEventListener('visibilitychange', handleVisibilityChange);
    window.removeEventListener('focus', markMessagesAsReadOnServer);
    document.removeEventListener('click', handleClickOutsideContextMenu, true); // Ensure this is removed
  }
  clearTimeout(stopTypingEmitTimer);
});

const formatMessageTimestamp = (timestamp) => {
  if (!timestamp) return '';
  return new Date(timestamp).toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' });
};

// Иконка статуса сообщения
const getMessageStatusIcon = (message) => {
  if (message.isSending) {
    return 'bi bi-clock'; // Отправка (часы)
  }
  // Для чата 1-на-1, если есть хотя бы один ID в readBy, и он не наш, значит собеседник прочитал
  const otherParticipant = getOtherParticipant();
  if (otherParticipant && message.readBy && message.readBy.includes(otherParticipant._id)) {
    return 'bi bi-check2-all'; // Прочитано (две галочки)
  }
  // Если сообщение доставлено (т.е. оно есть на сервере и не isSending), но не прочитано собеседником
  // (или readBy пуст/не содержит ID собеседника)
  return 'bi bi-check2'; // Доставлено (одна галочка)
  // Для групповых чатов логика была бы сложнее
};

// НОВАЯ ФУНКЦИЯ для обработки нативного события contextmenu
const handleNativeContextMenu = (event, message) => {
  if (message.sender?._id === currentUser.value?._id) {
    event.preventDefault(); // Prevent native context menu for own messages to show custom one
  }
  // For other users' messages, allow native context menu (e.g., for copying text).
};

const handleClickOutsideContextMenu = (event) => {
  if (contextMenu.value.visible && contextMenuRef.value && !contextMenuRef.value.contains(event.target)) {
    contextMenu.value.visible = false;
  }
};

</script>

<style scoped>
.chat-view-container {
  height: calc(100vh - 56px - 3rem); /* Примерная высота: 100% высоты вьюпорта минус шапка и отступы */
  /* Стилизуй это под свою шапку и футер */
}
.messages-area {
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
}
.message-bubble {
  padding: 0.5rem 1rem;
  border-radius: 1.25rem;
  max-width: 70%;
  word-wrap: break-word;
}
.message-bubble.sent {
  background-color: #0d6efd; /* Bootstrap primary */
  color: white;
  margin-left: auto; /* Прижимаем к правому краю */
  border-bottom-right-radius: 0.5rem;
}
.message-bubble.received {
  background-color: #e9ecef; /* Bootstrap light grey */
  color: #212529;
  margin-right: auto; /* Прижимаем к левому краю */
  border-bottom-left-radius: 0.5rem;
}
.message-content p {
  margin-bottom: 0.25rem;
}
.message-timestamp {
  font-size: 0.75em;
  display: block;
  text-align: right;
}
.message-bubble.received .message-timestamp {
  text-align: left;
  color: #6c757d !important; /* Немного темнее для серого фона */
}
.typing-indicator {
  font-size: 0.85em;
  min-height: 1.2em; /* Резервируем место, чтобы чат не прыгал */
}
.date-separator {
  font-size: 0.85em;
}
.date-separator .badge {
  padding: 0.4em 0.8em;
  font-weight: 500;
}

/* Новые стили для удаления сообщений и контекстного меню */
.message-item-wrapper {
  position: relative;
  display: flex;
  align-items: flex-start; /* Выравнивание по верху для bubble и кнопки */
  /* Добавляем небольшой отступ снизу для ясности, если нужно */
  /* margin-bottom: 4px;  */
}

.message-item-wrapper.sent-wrapper {
  justify-content: flex-end;
}
.message-item-wrapper.sent-wrapper .delete-message-btn {
  margin-left: 8px;
  order: 1; /* Кнопка справа от сообщения */
}

.message-item-wrapper.received-wrapper {
  justify-content: flex-start;
}

.delete-message-btn {
  align-self: center; /* Вертикальное центрирование кнопки относительно bubble */
  opacity: 0.6; /* Немного прозрачнее по умолчанию */
  transition: opacity 0.2s ease-in-out;
  padding: 0.2rem 0.4rem; /* Меньше padding */
  font-size: 0.8rem; /* Меньше шрифт иконки */
  line-height: 1; /* Убрать лишнюю высоту */
  background: transparent;
  border: none;
  color: #dc3545; /* Цвет иконки (Bootstrap danger) */
}
.delete-message-btn:hover,
.delete-message-btn:focus {
  opacity: 1;
  background: rgba(220, 53, 69, 0.1); /* Легкий фон при наведении/фокусе */
}
.delete-message-btn i {
  vertical-align: middle;
}

/* Стили для контекстного меню */
.context-menu {
  position: fixed;
  background-color: white;
  border: 1px solid #e0e0e0;
  box-shadow: 0 2px 10px rgba(0,0,0,0.15);
  border-radius: 6px;
  z-index: 1050; /* Выше большинства элементов Bootstrap */
  padding: 0;
  min-width: 180px;
}
.context-menu ul {
  list-style: none;
  padding: 5px 0; /* Adjusted padding for ul */
  margin: 0;
}
.context-menu li {
  padding: 10px 15px;
  cursor: pointer;
  font-size: 0.95rem;
  color: #333;
  display: flex;
  align-items: center;
}
.context-menu li:hover {
  background-color: #f5f5f5;
  color: #000;
}

.context-menu li i.bi-trash {
  margin-right: 10px;
  color: #dc3545; /* Bootstrap danger color */
  font-size: 1.1em; /* Slightly larger icon */
}

.context-menu li:hover i.bi-trash {
  color: #a71d2a; /* Darker danger color on hover */
}

/* ... other existing styles ... */
</style>