import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import axios from 'axios';

interface PaginationData {
  current_page: number;
  last_page: number;
  per_page: number;
  total: number;
  from?: number;
  to?: number;
}

interface UseInfiniteComercializadorasProps {
  initialItems: unknown[];
  initialPagination: PaginationData;
  filters?: Record<string, string>;
}

export const useInfiniteComercializadoras = ({
  initialItems,
  initialPagination,
  filters = {},
}: UseInfiniteComercializadorasProps) => {
  const [items, setItems] = useState(initialItems);
  const [pagination, setPagination] = useState(initialPagination);
  const [isLoading, setIsLoading] = useState(false);
  const [hasMore, setHasMore] = useState(
    initialPagination.current_page < initialPagination.last_page,
  );

  const sentinelRef = useRef<HTMLDivElement | null>(null);
  const loadingRef = useRef(false);
  const listGenerationRef = useRef(0);
  const inertiaPropsRef = useRef({ initialItems, initialPagination });
  inertiaPropsRef.current = { initialItems, initialPagination };

  const serverListFingerprint = useMemo(
    () =>
      [
        initialPagination.total,
        initialPagination.current_page,
        initialPagination.last_page,
        initialPagination.per_page,
        ...(initialItems || []).map((p: { CodCom?: number | string }) => String(p?.CodCom ?? '')),
      ].join('|'),
    [initialItems, initialPagination],
  );

  useEffect(() => {
    listGenerationRef.current += 1;
    const { initialItems: ip, initialPagination: pag } = inertiaPropsRef.current;
    setItems(ip);
    setPagination(pag);
    setHasMore(pag.current_page < pag.last_page);
    loadingRef.current = false;
  }, [serverListFingerprint]);

  const loadMore = useCallback(async () => {
    if (loadingRef.current || !hasMore) {
      return;
    }

    const generationAtStart = listGenerationRef.current;
    loadingRef.current = true;
    setIsLoading(true);

    try {
      const response = await axios.get(route('comercializadoras.load-more'), {
        params: {
          page: pagination.current_page + 1,
          per_page: pagination.per_page,
          ...filters,
        },
      });

      if (generationAtStart !== listGenerationRef.current) {
        return;
      }

      const newData = response.data;
      setItems((prev) => [...prev, ...(newData.data || [])]);
      setPagination({
        current_page: newData.current_page,
        last_page: newData.last_page,
        per_page: newData.per_page,
        total: newData.total,
        from: newData.from,
        to: newData.to,
      });
      setHasMore(newData.current_page < newData.last_page);
    } catch (error) {
      if ((error as { code?: string })?.code !== 'ERR_CANCELED') {
        console.error('Error cargando más comercializadoras:', error);
      }
    } finally {
      setIsLoading(false);
      loadingRef.current = false;
    }
  }, [pagination.current_page, pagination.per_page, hasMore, filters]);

  const resetWithFilters = useCallback(
    async (newFilters: Record<string, string>) => {
      const generationAtStart = listGenerationRef.current;
      setIsLoading(true);

      try {
        const response = await axios.get(route('comercializadoras.load-more'), {
          params: {
            page: 1,
            per_page: pagination.per_page,
            ...newFilters,
          },
        });

        if (generationAtStart !== listGenerationRef.current) {
          return;
        }

        const newData = response.data;
        setItems(newData.data || []);
        setPagination({
          current_page: newData.current_page,
          last_page: newData.last_page,
          per_page: newData.per_page,
          total: newData.total,
          from: newData.from,
          to: newData.to,
        });
        setHasMore(newData.current_page < newData.last_page);
      } catch (error) {
        if ((error as { code?: string })?.code !== 'ERR_CANCELED') {
          console.error('Error filtrando comercializadoras:', error);
        }
      } finally {
        setIsLoading(false);
      }
    },
    [pagination.per_page],
  );

  useEffect(() => {
    const el = sentinelRef.current;
    if (!el) {
      return undefined;
    }

    const observer = new IntersectionObserver(
      (entries) => {
        if (entries[0].isIntersecting && hasMore && !isLoading) {
          loadMore();
        }
      },
      { rootMargin: '200px' },
    );

    observer.observe(el);
    return () => observer.disconnect();
  }, [hasMore, isLoading, loadMore]);

  return {
    items,
    pagination,
    isLoading,
    hasMore,
    loadMore,
    resetWithFilters,
    sentinelRef,
  } as const;
};

export default useInfiniteComercializadoras;
