"use client";

import { useCallback, useMemo } from "react";
import { useRouter } from "next/navigation";

interface PageNavigationOptions<T> {
  data: T[];
  currentType: string;
  getTypeFromItem: (item: T) => string;
  // navigateToItemByType: (type: string) => void;
  getPageUrlByItem: (item: T) => string;
  onBeforeNext?: (nextItem: T) => boolean | Promise<boolean>;
  onBeforePrevious?: (prevItem: T) => boolean | Promise<boolean>;
  onComplete: () => void;
  onStart?: () => void;
}

interface PageNavigationReturn<T> {
  data: T[];
  currentItem: T | undefined;
  currentIndex: number;
  isFirst: boolean;
  isLast: boolean;
  hasNext: boolean;
  hasPrevious: boolean;
  goToNext: () => Promise<void>;
  goToPrevious: () => Promise<void>;
  goToFirst: () => Promise<void>;
  goToLast: () => Promise<void>;
  goToIndex: (index: number) => Promise<void>;
  getNextPageUrl: () => string | undefined;
  totalPages: number;
}

export function useMultiPageNavigation<T>({
  data,
  currentType,
  getTypeFromItem,
  // navigateToItemByType,
  getPageUrlByItem,
  onBeforeNext,
  onBeforePrevious,
  onComplete,
  onStart,
}: PageNavigationOptions<T>): PageNavigationReturn<T> {
  const router = useRouter();

  const currentIndex = useMemo(
    () => data.findIndex(item => getTypeFromItem(item) === currentType),
    [data, currentType, getTypeFromItem]
  );

  const currentItem = useMemo(() => data[currentIndex], [data, currentIndex]);
  const nextItem = useMemo(() => data[currentIndex + 1], [data, currentIndex]);

  const isFirst = currentIndex === 0;
  const isLast = currentIndex === data.length - 1;
  const hasNext = !isLast;
  const hasPrevious = !isFirst;
  const totalPages = data.length;

  const navigateToItem = useCallback(
    async (item: T) => {
      // const type = getTypeFromItem(item);
      // navigateToItemByType(type);
      router.push(getPageUrlByItem(item));
    },
    [getPageUrlByItem, router]
  );

  const goToNext = useCallback(async () => {
    if (!hasNext) return onComplete();

    const nextItem = data[currentIndex + 1];

    if (onBeforeNext) {
      const shouldProceed = await onBeforeNext(nextItem);
      if (!shouldProceed) return;
    }

    await navigateToItem(nextItem);
  }, [hasNext, data, currentIndex, onBeforeNext, onComplete, navigateToItem]);

  const goToPrevious = useCallback(async () => {
    if (!hasPrevious) return;

    const prevItem = data[currentIndex - 1];

    if (onBeforePrevious) {
      const shouldProceed = await onBeforePrevious(prevItem);
      if (!shouldProceed) return;
    }

    await navigateToItem(prevItem);
  }, [hasPrevious, data, currentIndex, onBeforePrevious, navigateToItem]);

  const goToFirst = useCallback(async () => {
    if (isFirst) return;

    if (onStart) {
      onStart();
      return;
    }

    await navigateToItem(data[0]);
  }, [isFirst, onStart, navigateToItem, data]);

  const goToLast = useCallback(async () => {
    if (isLast) return;
    await navigateToItem(data[data.length - 1]);
  }, [isLast, navigateToItem, data]);

  const goToIndex = useCallback(
    async (index: number) => {
      if (index < 0 || index >= data.length || index === currentIndex) return;
      await navigateToItem(data[index]);
    },
    [data, currentIndex, navigateToItem]
  );

  const getNextPageUrl = useCallback(() => {
    if (!hasNext || !nextItem) return;
    return getPageUrlByItem(nextItem);
  }, [getPageUrlByItem, hasNext, nextItem]);

  return useMemo(
    () => ({
      data,
      currentItem,
      nextItem,
      currentIndex,
      isFirst,
      isLast,
      hasNext,
      hasPrevious,
      goToNext,
      goToPrevious,
      goToFirst,
      goToLast,
      goToIndex,
      getTypeFromItem,
      getNextPageUrl,
      totalPages,
    }),
    [
      data,
      currentItem,
      nextItem,
      currentIndex,
      isFirst,
      isLast,
      hasNext,
      hasPrevious,
      goToNext,
      goToPrevious,
      goToFirst,
      goToLast,
      goToIndex,
      getTypeFromItem,
      getNextPageUrl,
      totalPages,
    ]
  );
}
