import { ref, shallowRef, watch, computed } from 'vue';
import { useNuxtApp } from '#app';
import { collection } from 'firebase/firestore';
import { useUserStore } from '@/stores/user';
import { deleteSelected } from '@/utils/boardUtils';
import { fetchCountsFromFunction } from '~/utils/api/countBoards';
import { fetchBoardsFromFunction } from '~/utils/api/fetchBoardsFromFunction';
import type {
  BoardItem,
  OrderByDirection,
  SortOption,
  CursorResponse,
  UseBoardListOptions,
} from '@/types';

export function useBoardList<T extends BoardItem>(
  currentCollection: string,
  options: UseBoardListOptions = {}
) {
  const {
    title = 'Board',
    itemsPerPage = 20,
    defaultSort = 'desc',
    access = 'public',
    loadingMessage = '잠시만 기다려주세요...',
  } = options;
  /* UI + meta */
  const compdata = ref({ title });
  const isLoading = ref(false);
  const sortingOrder = ref<OrderByDirection>(defaultSort);

  /* count for numbered buttons */
  const totalItems = ref(0);
  const totalPages = computed(() => Math.ceil(totalItems.value / itemsPerPage));
  const pageNumbers = computed(() =>
    Array.from({ length: totalPages.value }, (_, i) => i + 1)
  );

  /* cursor bookkeeping */
  const currentPage = ref(1); // 1‑based for templates
  const pageCursors = shallowRef<string[]>([]); // token that *starts* each page (page 1 = undefined)
  const nextPageToken = ref<string | null>(null);
  const hasMore = computed(() => !!nextPageToken.value);

  /* data */
  const currentItems = ref<T[]>([]);

  /* selection helpers */
  const selectedItems = shallowRef<T[]>([]);
  const showSelectBoxes = ref(false);

  const sortOptions: SortOption[] = [
    { sortId: 1, name: '내림차순', rule: 'desc' },
    { sortId: 2, name: '오름차순', rule: 'asc' },
  ];
  const selectedSort = ref<SortOption>(sortOptions[0]!);
  /* user role (for conditional buttons etc.) */
  const userRole = computed(() => useUserStore().userRole);

  const fetchPageData = async (
    token: string | undefined
  ): Promise<CursorResponse<T>> =>
    fetchBoardsFromFunction<T>(currentCollection, {
      sortOrder: sortingOrder.value,
      itemsPerPage,
      access,
      pageToken: token,
    });

  //  Fetch a specific *numbered* page
  //  (builds cursors as it goes so later jumps are free)
  const fetchPage = async (page: number) => {
    isLoading.value = true;
    try {
      /* 1. Count only once (needed for numbered buttons) */
      if (page === 1) {
        totalItems.value = await fetchCountsFromFunction(
          currentCollection,
          access
        );
      }

      /* 2. Ensure we have cursors up to (page‑1) -------------------- */
      while (pageCursors.value.length < page - 1 && hasMore.value) {
        await loadMore(); // walk forward & cache
      }

      /* 3. Now fetch the requested page ---------------------------- */
      const tokenForPage = pageCursors.value[page - 1] || undefined;
      const res = await fetchPageData(tokenForPage);

      currentItems.value = res.items;
      nextPageToken.value = res.nextPageToken;
      currentPage.value = page;

      /* 4. Record cursor for NEXT page (index = page) -------------- */
      if (pageCursors.value.length < page)
        pageCursors.value[page] = res.nextPageToken ?? '';
    } finally {
      isLoading.value = false;
    }
  };

  /* Infinite scroll / "Load more" */
  const loadMore = async () => {
    if (!hasMore.value || isLoading.value) return;
    isLoading.value = true;
    try {
      const res = await fetchPageData(nextPageToken.value || undefined);

      currentItems.value = [...currentItems.value, ...res.items] as T[];

      /* record start token of the *new* page */
      pageCursors.value.push(nextPageToken.value ?? '');
      nextPageToken.value = res.nextPageToken;
      currentPage.value += 1;
    } finally {
      isLoading.value = false;
    }
  };
  /* ----------------------------------------------------------------
     Navigation helpers
  ---------------------------------------------------------------- */
  const onGoToPage = (n: number) => fetchPage(n);
  const onPrevPage = () =>
    currentPage.value > 1 && fetchPage(currentPage.value - 1);
  const onNextPage = () =>
    currentPage.value < totalPages.value && fetchPage(currentPage.value + 1);

  /* ----------------------------------------------------------------
     Selection / deletion
  ---------------------------------------------------------------- */
  const onToggleSelect = (item: T) => {
    const idx = selectedItems.value.findIndex((i) => i.docId === item.docId);
    selectedItems.value =
      idx === -1
        ? [...selectedItems.value, item]
        : selectedItems.value.filter((i) => i.docId !== item.docId);
  };

  const onDeleteSelected = async () => {
    if (!import.meta.client) return;
    const { $firebase } = useNuxtApp();
    const collectionRef = collection($firebase.db, currentCollection);
    await deleteSelected(
      selectedItems,
      showSelectBoxes,
      collectionRef,
      $firebase.storage
    );
    await fetchPage(currentPage.value);
  };

  /* ----------------------------------------------------------------
     React to sort‑order change
  ---------------------------------------------------------------- */
  watch(
    selectedSort,
    () => {
      sortingOrder.value = selectedSort.value.rule;
      // reset paging
      currentPage.value = 1;
      pageCursors.value = [];
      nextPageToken.value = null;
      fetchPage(1);
    },
    { immediate: true }
  );
  return {
    compdata,
    currentItems,
    currentPage,
    totalPages,
    pageNumbers,
    selectedItems,
    showSelectBoxes,
    selectedSort,
    sortOptions,
    sortingOrder,
    userRole,
    isLoading,
    loadingMessage,
    hasMore, // <-- new
    loadMore,
    onToggleSelect,
    onDeleteSelected,
    onGoToPage,
    onPrevPage,
    onNextPage,
  };
}
