import { useEffect, useImperativeHandle, forwardRef } from "react";
import { NoteItem } from "./NoteItem";
import { useAppSelector, useAppDispatch } from "../../store/hooks";
import { offlineNotesApi } from "../../api/offlineNotesApi";
import { setNotes, setAllNotes } from "../../store/slices/notesSlice";
import { useNotification } from "../../hooks/useNotification";
import { extractTags } from "../../utils/markdown";

export interface NotesListRef {
  reloadNotes: () => void;
  focusNote: (noteId: number | string) => void;
}

interface NotesListProps {
  selectedNoteIds?: (number | string)[];
  onNoteSelect?: (noteId: number | string) => void;
}

export const NotesList = forwardRef<NotesListRef, NotesListProps>(
  ({ selectedNoteIds = [], onNoteSelect }, ref) => {
  const notes = useAppSelector((state) => state.notes.notes);
  const userId = useAppSelector((state) => state.auth.userId);
  const searchQuery = useAppSelector((state) => state.notes.searchQuery);
  const selectedDate = useAppSelector((state) => state.notes.selectedDate);
  const selectedTag = useAppSelector((state) => state.notes.selectedTag);
  const dispatch = useAppDispatch();
  const { showNotification } = useNotification();

  // Функция для загрузки данных (используется для reloadNotes)
  const loadNotes = async () => {
    try {
      // Всегда загружаем все заметки для тегов и календаря
      const allData = await offlineNotesApi.getAll();
      let filteredAllData = allData;
      if (userId) {
        filteredAllData = allData.filter((note) => note.user_id === userId);
      }
      dispatch(setAllNotes(filteredAllData));

      // Для списка заметок: если есть фильтры - делаем поисковый запрос, иначе используем все заметки
      let notesData;
      if (searchQuery || selectedDate || selectedTag) {
        notesData = await offlineNotesApi.search({
          q: searchQuery || undefined,
          date: selectedDate || undefined,
          tag: selectedTag || undefined,
        });
        // Дополнительная проверка на клиенте
        if (userId) {
          notesData = notesData.filter((note) => note.user_id === userId);
        }
        
        // Точная фильтрация по тегу на клиенте (регистронезависимо)
        // SQLite LOWER() плохо работает с кириллицей, поэтому фильтруем здесь
        if (selectedTag) {
          const selectedTagLower = selectedTag.toLowerCase();
          notesData = notesData.filter((note) => {
            const noteTags = extractTags(note.content);
            return noteTags.some(tag => tag.toLowerCase() === selectedTagLower);
          });
        }
      } else {
        // Если нет фильтров, используем все заметки
        notesData = filteredAllData;
      }

      // Фильтруем архивные заметки из основного списка
      notesData = notesData.filter((note) => note.is_archived === 0);

      dispatch(setNotes(notesData));
    } catch (error) {
      console.error("Ошибка загрузки заметок:", error);
      showNotification("Ошибка загрузки заметок", "error");
    }
  };

  // Объединенная загрузка данных при изменении зависимостей
  useEffect(() => {
    if (userId) {
      loadNotes();
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [userId, searchQuery, selectedDate, selectedTag]);

  const focusNote = (noteId: number | string) => {
    // Используем data-атрибут для поиска элемента заметки
    const noteElement = document.querySelector(
      `[data-note-id="${noteId}"]`
    ) as HTMLDivElement | null;
    
    if (noteElement) {
      // Прокручиваем к верхней части заметки
      noteElement.scrollIntoView({ behavior: "smooth", block: "start", inline: "nearest" });
      // Добавляем визуальное выделение на короткое время
      // Очищаем предыдущий таймер, если он был установлен
      const existingTimeout = (noteElement as any).__focusTimeout;
      if (existingTimeout) {
        clearTimeout(existingTimeout);
      }
      noteElement.style.transition = "box-shadow 0.3s ease";
      noteElement.style.boxShadow = "0 0 0 3px rgba(33, 150, 243, 0.5)";
      const timeout = setTimeout(() => {
        noteElement.style.boxShadow = "";
        (noteElement as any).__focusTimeout = null;
      }, 2000);
      (noteElement as any).__focusTimeout = timeout;
    }
  };

  useImperativeHandle(ref, () => ({
    reloadNotes: loadNotes,
    focusNote: focusNote,
  }));

  const handleDelete = async (id: number | string) => {
    try {
      await offlineNotesApi.delete(id);
      showNotification("Заметка удалена", "success");
      loadNotes();
    } catch (error) {
      console.error("Ошибка удаления заметки:", error);
      showNotification("Ошибка удаления заметки", "error");
    }
  };

  const handlePin = async (id: number | string) => {
    try {
      await offlineNotesApi.pin(id);
      loadNotes();
    } catch (error) {
      console.error("Ошибка закрепления заметки:", error);
      showNotification("Ошибка закрепления заметки", "error");
    }
  };

  const handleArchive = async (id: number | string) => {
    try {
      await offlineNotesApi.archive(id);
      showNotification("Заметка архивирована", "success");
      loadNotes();
    } catch (error) {
      console.error("Ошибка архивирования заметки:", error);
      showNotification("Ошибка архивирования заметки", "error");
    }
  };

  if (notes.length === 0) {
    let message = "Заметок пока нет. Создайте первую!";
    if (selectedDate && selectedTag) {
      message = `Нет заметок за ${selectedDate} с тегом #${selectedTag}`;
    } else if (selectedDate) {
      message = `Нет заметок за выбранную дату (${selectedDate})`;
    } else if (selectedTag) {
      message = `Нет заметок с тегом #${selectedTag}`;
    } else if (searchQuery) {
      message = "Ничего не найдено по запросу";
    }

    return (
      <div className="notes-container">
        <p className="empty-message">{message}</p>
      </div>
    );
  }

  // Сортируем заметки: сначала закрепленные по времени закрепления, потом незакрепленные по дате создания (новые сверху)
  const sortedNotes = [...notes].sort((a, b) => {
    if (a.is_pinned !== b.is_pinned) {
      return b.is_pinned - a.is_pinned;
    }

    // Если обе заметки закреплены, сортируем по времени закрепления
    if (a.is_pinned && b.is_pinned) {
      const pinnedA = a.pinned_at ? new Date(a.pinned_at).getTime() : 0;
      const pinnedB = b.pinned_at ? new Date(b.pinned_at).getTime() : 0;
      return pinnedB - pinnedA; // Более свежие закрепления сверху
    }

    // Для незакрепленных заметок сортируем по дате создания
    const dateA = new Date(a.created_at).getTime();
    const dateB = new Date(b.created_at).getTime();
    return dateB - dateA;
  });

  return (
    <div className="notes-container">
      {sortedNotes.map((note) => (
        <NoteItem
          key={note.id}
          note={note}
          onDelete={handleDelete}
          onPin={handlePin}
          onArchive={handleArchive}
          onReload={loadNotes}
          isSelected={selectedNoteIds.includes(note.id)}
          onSelect={onNoteSelect}
          onFocusNote={focusNote}
        />
      ))}
    </div>
  );
});
