<template>
  <div class="w-full sm:w-4/5 dark:text-neutral-300">
    <div class="bg-white flex justify-between p-3 lg:p-5 dark:bg-gray-800">
      <div class="flex flex-col md:flex-row">
        <div class="relative">
          <img
            v-if="isDarkMode"
            src="https://img.icons8.com/?size=100&id=WwWusvLMTFd7&format=png&color=000000"
            class="absolute top-4 left-3 h-5"
          />
          <img
            v-else
            src="https://img.icons8.com/?size=100&id=zR5EBMqZTIBz&format=png&color=000000"
            class="absolute top-4 left-3 h-5"
          />
          <input
            v-model="poisk"
            type="text"
            placeholder="Поиск..."
            class="dark:bg-gray-900 border-slate-100 shadow rounded-xl p-3 pl-11"
          />
        </div>
        <select
          @change="onfilterItems($event.target.value)"
          class="dark:bg-gray-900 border-slate-100 shadow rounded-xl h-12 p-3 mt-3 md:mt-0 md:ml-4"
        >
          <option value="all">Все</option>
          <option value="time">По времени</option>
          <option value="viewed">Просмотренные</option>
          <option value="status">Избранные</option>
        </select>
      </div>
      <Time />
    </div>

    <div ref="scrollContainer" class="p-4">
      <Stat
        v-for="item in items"
        :key="item.url"
        :url="item.url"
        :title="item.title"
        :article_date="item.article_date"
        :short_text="item.short_text"
        :category="item.category"
        :parsed_at="item.parsed_at"
        :status="item.status"
        :viewed="item.viewed"
        :original_text="item.original_text"
        :translation_text="item.translation_text"
        :other="item.other"
        @update:viewed="handleViewedChange"
        @update:status="handleStatusChange"
      />
      <!-- Sentinel для бесконечного скролла -->
      <div ref="sentinel" class="h-4"></div>
      <div v-if="isLoading" class="text-center p-4">Загрузка...</div>
      <div v-if="!hasMore && items.length > 0" class="text-center p-4">
        Все загружено
      </div>
    </div>
  </div>
</template>

<script setup>
import { ref, onMounted, onUnmounted, watch, nextTick } from "vue";
import Stat from "./One_kard.vue";
import Time from "./Time.vue";
import axios from "axios";

const props = defineProps({
  filter: { type: String, default: "all" },
});

// Константы
const LIMIT = 50;
const POLL_INTERVAL = 15000; // 15 секунд

// Состояния
const isDarkMode = ref(document.documentElement.classList.contains("dark"));
const sentinel = ref(null);
const scrollContainer = ref(null); // Реф контейнера скролла
const isLoading = ref(false);
const hasMore = ref(true);
const items = ref([]);
const poisk = ref("");

// Пагинация
let currentFilter = "default";
let currentOffset = 0;
let pollTimer = null;
let lastScrollTop = 0; // Сохраняем позицию скролла


const fetchData = async (url) => {
  try {
    const { data } = await axios.get(url);
    return data;
  } catch (err) {
    console.error(`Ошибка при получении данных:`, err);
    return [];
  }
};

const fetchTotalCount = async (filterValue) => {
  try {
    const { data } = await axios.get(
      `https://allowlgroup.ru/api/8002/records_all/count?item=${filterValue}`,
    );
    return data.count;
  } catch (err) {
    console.error("Ошибка при получении количества:", err);
    return 0;
  }
};

const fetchSearchCount = async (query, filterValue) => {
  try {
    const { data } = await axios.get(
      `https://allowlgroup.ru/api/8002/poisk/count?query=${query}&item=${filterValue}`,
    );
    return data.count;
  } catch (err) {
    console.error("Ошибка при получении количества:", err);
    return 0;
  }
};

// === Загрузка данных ===

const loadItems = async (filterValue, append = false) => {
  if (isLoading.value) return;

  isLoading.value = true;

  if (!append) {
    items.value = [];
    currentOffset = 0;
    hasMore.value = true;
  }

  currentFilter = filterValue;

  try {
    const url = poisk.value.trim()
      ? `https://allowlgroup.ru/api/8002/poisk?query=${poisk.value}&item=${filterValue}&offset=${currentOffset}&limit=${LIMIT}`
      : `https://allowlgroup.ru/api/8002/records_all?item=${filterValue}&offset=${currentOffset}&limit=${LIMIT}`;

    const totalCount = poisk.value.trim()
      ? await fetchSearchCount(poisk.value, filterValue)
      : await fetchTotalCount(filterValue);

    const data = await fetchData(url);

    if (append) {
      items.value = [...items.value, ...data];
    } else {
      items.value = data;
    }

    currentOffset += LIMIT;
    hasMore.value = currentOffset < totalCount;
  } finally {
    isLoading.value = false;
  }
};

// === Polling - проверка новых данных ===

const checkForUpdates = async () => {
  // Не проверяем при активном поиске или загрузке
  if (isLoading.value || (poisk.value && poisk.value.trim())) {
    return;
  }

  try {
    const totalCount = await fetchTotalCount(currentFilter);
    const data = await fetchData(
      `https://allowlgroup.ru/api/8002/records_all?item=${currentFilter}&offset=0&limit=${LIMIT}`,
    );

    if (!data.length) return;

    // Создаём Map существующих URL для быстрого поиска
    const existingUrls = new Map(items.value.map((item) => [item.url, item]));

    const newItems = [];
    let hasNew = false;

    for (const item of data) {
      const existing = existingUrls.get(item.url);

      if (!existing) {
        // Новая запись - добавляем в начало
        newItems.push(item);
        hasNew = true;
      } else if (
        existing.viewed !== item.viewed ||
        existing.status !== item.status
      ) {
        // Изменились viewed/status - обновляем
        const index = items.value.indexOf(existing);
        items.value[index] = { ...item };
        hasNew = true;
      }
    }

    // Добавляем новые записи в начало
    if (newItems.length > 0) {
      items.value = [...newItems, ...items.value];
    }
  } catch (err) {
    console.error("Ошибка при проверке обновлений:", err);
  }
};

const startPolling = () => {
  stopPolling();
  pollTimer = setInterval(checkForUpdates, POLL_INTERVAL);
};

const stopPolling = () => {
  if (pollTimer) {
    clearInterval(pollTimer);
    pollTimer = null;
  }
};

// === Обработчики событий от Stat ===

const handleViewedChange = ({ url, viewed }) => {
  const item = items.value.find((i) => i.url === url);
  if (item) item.viewed = viewed;
};

const handleStatusChange = ({ url, status }) => {
  const item = items.value.find((i) => i.url === url);
  if (item) item.status = status;
};

// === Watch ===

let debounceTimer = null;
watch(poisk, (newVal) => {
  clearTimeout(debounceTimer);
  debounceTimer = setTimeout(() => {
    currentOffset = 0;
    loadItems(currentFilter);
  }, 800);
});

watch(
  () => props.filter,
  (newFilter) => {
    const filterValue = newFilter === "all" ? "default" : newFilter;
    currentFilter = filterValue;
    poisk.value = "";
    loadItems(filterValue);
  },
);

const onfilterItems = (filterValue) => {
  const filter = filterValue === "all" ? "default" : filterValue;
  loadItems(filter);
};

// === Lifecycle ===

let observer = null;

onMounted(() => {
  // Тема
  isDarkMode.value = document.documentElement.classList.contains("dark");
  const mutationObserver = new MutationObserver(() => {
    isDarkMode.value = document.documentElement.classList.contains("dark");
  });
  mutationObserver.observe(document.documentElement, {
    attributes: true,
    attributeFilter: ["class"],
  });

  // Загрузка данных
  const initialFilter = props.filter === "all" ? "default" : props.filter;
  currentFilter = initialFilter;
  loadItems(initialFilter);

  // Запускаем polling
  startPolling();

  // Observer для бесконечного скролла
  nextTick(() => {
    observer = new IntersectionObserver(
      (entries) => {
        if (entries[0].isIntersecting && hasMore.value) {
          loadItems(currentFilter, true); // append = true
        }
      },
      { rootMargin: "100px" },
    );

    if (sentinel.value) {
      observer.observe(sentinel.value);
    }
  });
});

onUnmounted(() => {
  stopPolling();
  if (observer) observer.disconnect();
});
</script>
