import { FlashList, ListRenderItem } from "@shopify/flash-list";
import React, { useCallback, useEffect, useRef, useState } from "react";
import { RefreshControl, Text, View } from "react-native";
import { AsyncContent } from "./AsyncContent";

export type PaginatedFlashListProps = {
  pageSize?: number;
  sortingParam?: string;
  statusParam?: string;
  estimatedItemSize?: number;
  fetchFunction: (params: {
    sortingParam?: string;
    statusParam?: string;
    page: number;
    pageSize: number;
  }) => Promise<any>;
  renderItem: ListRenderItem<any>;
  ListEmptyComponent:
    | React.ReactElement<
        unknown,
        string | React.JSXElementConstructor<any>
      >
    | React.ComponentType<any>
    | undefined;
};

const PAGE_SIZE = 10;

export function PaginatedFlashList({
  pageSize = PAGE_SIZE,
  sortingParam,
  statusParam,
  estimatedItemSize = 120,
  renderItem,
  fetchFunction,
  ListEmptyComponent,
}: PaginatedFlashListProps) {
  const [data, setData] = useState<unknown[]>();
  const [refreshing] = useState(false);
  const [loading, setLoading] = useState(false);

  const pageRef = useRef(0);
  const hasNextPageRef = useRef(true);

  const onRefresh = useCallback(() => {
    setData(undefined);
    hasNextPageRef.current = true;
    pageRef.current = 0;
    onLoad();
  }, []);

  const keyExtractor = useCallback(
    (item: unknown) => (item as { id: string }).id,
    []
  );
  const onEndReached = useCallback(() => onLoad(), []);

  const onLoad = useCallback(() => {
    if (loading || !hasNextPageRef.current) return;
    setLoading(true);
    fetchFunction({
      sortingParam,
      statusParam,
      pageSize,
      page: pageRef.current,
    })
      .then((response) => {
        hasNextPageRef.current =
          (response.totalCount || 0) > (pageRef.current + 1) * pageSize;
        const newData = response.items || [];
        setData((prevData) => {
          if (prevData) {
            return [...prevData, ...newData];
          }
          return newData;
        });
        pageRef.current += 1;
      })
      .catch((error) => {
        console.error("Error fetching data:", error);
      })
      .finally(() => {
        setLoading(false);
      });
  }, [fetchFunction, sortingParam, statusParam, loading]);

  const Separator = useCallback(() => <View className="h-2" />, []);
  const LoadingFooter = useCallback(() => {
    if (!loading) return null;
    return (
      <View className="flex-row justify-center py-4">
        <Text className="text-gray-500">Loading more...</Text>
      </View>
    );
  }, [loading]);

  useEffect(() => {
    onLoad();
  }, []);

  if (data === undefined) {
    return <AsyncContent isLoading={true} loadingIcon="pricetag" />;
  }

  return (
    <FlashList
      data={data}
      refreshControl={
        <RefreshControl refreshing={refreshing} onRefresh={onRefresh} />
      }
      renderItem={renderItem}
      estimatedItemSize={estimatedItemSize}
      keyExtractor={keyExtractor}
      onEndReached={onEndReached}
      onEndReachedThreshold={0.5}
      ItemSeparatorComponent={Separator}
      ListFooterComponent={LoadingFooter}
      ListEmptyComponent={ListEmptyComponent}
    />
  );
}
