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 Props {
  initialItems: unknown[];
  initialPagination: PaginationData;
  filters?: Record<string, string>;
}

export const useInfiniteTarifas = ({ initialItems, initialPagination, filters = {} }: Props) => {
  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(
    () =>
      [
        filters.tipo,
        initialPagination.total,
        initialPagination.current_page,
        ...(initialItems || []).map((p: { id?: number | string }) => String(p?.id ?? '')),
      ].join('|'),
    [initialItems, initialPagination, filters.tipo],
  );

  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('tarifas.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) {
      console.error('Error cargando más tarifas:', 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('tarifas.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) {
        console.error('Error filtrando tarifas:', 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 useInfiniteTarifas;
