/* eslint-disable react-hooks/refs */
import { useWindowVirtualizer } from "@tanstack/react-virtual";
import { useAtom } from "jotai";
import * as React from "react";
import { useEffect, useLayoutEffect } from "react";

//import { useInView } from "react-intersection-observer";
import { UniversalPostRendererATURILoader } from "~/components/UniversalPostRenderer";
import { useAuth } from "~/providers/UnifiedAuthProvider";
import { feedHeightsAtom, feedScrollIndexAtom } from "~/utils/atoms";
import { useInfiniteQueryFeedSkeleton } from "~/utils/useQuery";

interface InfiniteCustomFeedProps {
  feedUri: string;
  pdsUrl?: string;
  feedServiceDid?: string;
  initialScrollIndex?: number;
  //onVisibleIndexChange?: (index: number) => void;
}

export function InfiniteCustomFeed({
  feedUri,
  pdsUrl,
  feedServiceDid,
  initialScrollIndex,
  //onVisibleIndexChange,
}: InfiniteCustomFeedProps) {
  const OVERSCAN_COUNT = 10;
  const ESTIMATE_HEIGHT = 150;

  const { agent } = useAuth();
  const authed = !!agent?.did;

  const listRef = React.useRef<HTMLDivElement | null>(null);
  const [offsetTop, setOffsetTop] = React.useState(0);
  const [scrollIndexes, setScrollIndexes] = useAtom(feedScrollIndexAtom);
  //const initialScrollIndex = scrollIndexes[feedUri];

  // const identityresultmaybe = useQueryIdentity(agent?.did);
  // const identity = identityresultmaybe?.data;
  // const feedGenGetRecordQuery = useQueryArbitrary(feedUri);

  const {
    data,
    error,
    isLoading,
    isError,
    hasNextPage,
    fetchNextPage,
    isFetchingNextPage,
    refetch,
    isRefetching,
  } = useInfiniteQueryFeedSkeleton({
    feedUri: feedUri,
    agent: agent ?? undefined,
    isAuthed: authed ?? false,
    pdsUrl: pdsUrl,
    feedServiceDid: feedServiceDid,
  });

  const handleRefresh = () => {
    refetch();
  };

  //const { ref, inView } = useInView();

  // React.useEffect(() => {
  //   if (inView && hasNextPage && !isFetchingNextPage) {
  //     fetchNextPage();
  //   }
  // }, [inView, hasNextPage, isFetchingNextPage, fetchNextPage]);

  const allPosts = React.useMemo(() => {
    const flattenedPosts = data?.pages.flatMap((page) => page?.feed) ?? [];

    const seenUris = new Set<string>();

    return flattenedPosts.filter((item) => {
      if (!item?.post) return false;

      if (seenUris.has(item.post)) {
        return false;
      }

      seenUris.add(item.post);
      return true;
    });
  }, [data]);

  const [feedHeights, setFeedHeights] = useAtom(feedHeightsAtom);
  const currentFeedCache = feedHeights[feedUri] ?? {};

  const virtualizerRef = React.useRef<ReturnType<
    typeof useWindowVirtualizer
  > | null>(null);

  const virtualizer = useWindowVirtualizer({
    count: allPosts.length,
    //  +
    // (isFetchingNextPage ? 1 : 0) +
    // (hasNextPage && !isFetchingNextPage ? 1 : 0) +
    // (!hasNextPage ? 1 : 0) +
    // 1,
    estimateSize: (index) => {
      const post = allPosts[index];
      if (!post) return ESTIMATE_HEIGHT;

      if (currentFeedCache[post.post]) {
        return currentFeedCache[post.post];
      }

      return ESTIMATE_HEIGHT;
    },
    // measureElement: measureElement,
    overscan: OVERSCAN_COUNT,
    scrollMargin: offsetTop,
  });
  // React.useEffect(() => {
  //   virtualizer.measure();
  // }, [data]);

  const measureElement = React.useCallback(
    (node: HTMLElement | null) => {
      if (!node) return;

      virtualizer.measureElement(node);

      const postUri = node.dataset.postUri;
      const newHeight = node.offsetHeight;

      if (postUri && newHeight > 0 && currentFeedCache[postUri] !== newHeight) {
        setFeedHeights((prev) => ({
          ...prev,
          [feedUri]: {
            ...prev[feedUri],
            [postUri]: newHeight,
          },
        }));
      }
    },
    [virtualizer, setFeedHeights, feedUri, currentFeedCache]
  );

  virtualizerRef.current = virtualizer;

  useLayoutEffect(() => {
    const update = () => {
      if (listRef.current) {
        setOffsetTop(listRef.current.offsetTop);
      }
      //if (virtualizerRef.current) {
      //        virtualizerRef.current.measure();
      //    }
    };

    update();

    let debounceTimeout: NodeJS.Timeout;

    const debouncedUpdate = () => {
      clearTimeout(debounceTimeout);
      debounceTimeout = setTimeout(update, 100);
    };

    window.addEventListener("resize", debouncedUpdate);

    return () => {
      window.removeEventListener("resize", debouncedUpdate);
      clearTimeout(debounceTimeout);
    };
  }, []);

  const hasRestoredScroll = React.useRef(false);
  useLayoutEffect(() => {
    if (
      hasRestoredScroll.current ||
      !initialScrollIndex ||
      initialScrollIndex === 0
    ) {
      return;
    }

    if (initialScrollIndex < allPosts.length) {
      console.log(`Restoring scroll to index: ${initialScrollIndex}`);
      virtualizer.scrollToIndex(initialScrollIndex, {
        align: "start",
        behavior: "auto",
      });
      hasRestoredScroll.current = true;
    }
  }, [initialScrollIndex, allPosts.length, virtualizer]);

  // React.useEffect(() => {
  //   const handleScroll = () => {
  //     const topVisibleItem = virtualizer.getVirtualItems()[0];
  //     if (topVisibleItem && onVisibleIndexChange) {
  //       onVisibleIndexChange(topVisibleItem.index);
  //     }
  //   };

  //   window.addEventListener('scroll', handleScroll, { passive: true });
  //   return () => window.removeEventListener('scroll', handleScroll);
  // }, [virtualizer, onVisibleIndexChange]);

  useEffect(() => {
    return () => {
      const topVisibleItem = virtualizer.getVirtualItems()[OVERSCAN_COUNT];

      if (topVisibleItem) {
        console.log(
          `Saving final scroll index ${topVisibleItem.index} for feed ${feedUri}`
        );
        setScrollIndexes((prev) => ({
          ...prev,
          [feedUri]: topVisibleItem.index,
        }));
      }
    };
  }, [virtualizer, feedUri, setScrollIndexes]);

  if (isLoading) {
    return <div className="p-4 text-center text-gray-500">Loading feed...</div>;
  }

  if (isError) {
    return (
      <div className="p-4 text-center text-red-500">Error: {error.message}</div>
    );
  }

  if (!allPosts || typeof allPosts !== "object" || allPosts.length === 0) {
    return (
      <div className="p-4 text-center text-gray-500">
        No posts in this feed.
      </div>
    );
  }

  //if (offsetTop === 0) {
  //   return <div ref={listRef}>Calculating...</div>;
  //}

  return (
    <>
      <div ref={listRef}>
        <div
          style={{
            height: `${virtualizer.getTotalSize()}px`,
            width: "100%",
            position: "relative",
          }}
        >
          {virtualizer.getVirtualItems().map((virtualItem) => {
            const item = allPosts[virtualItem.index];
            const i = virtualItem.index;
            if (item)
              return (
                <UniversalPostRendererATURILoader
                  key={item.post || i}
                  atUri={item.post}
                  dataIndexPropPass={i}
                  feedviewpost={true}
                  ref={measureElement}
                  repostedby={
                    !!item.reason?.$type && (item.reason as any)?.repost
                  }
                  style={{
                    position: "absolute",
                    top: 0,
                    left: 0,
                    width: "100%",
                    //height: `${item.size}px`,
                    transform: `translateY(${virtualItem.start - offsetTop}px)`,
                  }}
                />
              );
          })}
        </div>
      </div>

      {/* allPosts?: {allPosts ? "true" : "false"}
      hasNextPage?: {hasNextPage ? "true" : "false"}
      isFetchingNextPage?: {isFetchingNextPage ? "true" : "false"} */}
      {isFetchingNextPage && (
        <div className="p-4 text-center text-gray-500">Loading more...</div>
      )}
      {hasNextPage && !isFetchingNextPage && (
        <button
          onClick={() => fetchNextPage()}
          className="w-[calc(100%-2rem)] mx-4 my-4 px-4 py-2 bg-gray-100 dark:bg-gray-800 text-gray-800 dark:text-gray-200 rounded-lg hover:bg-gray-200 dark:hover:bg-gray-700 font-semibold"
        >
          Load More Posts
        </button>
      )}
      {!hasNextPage && (
        <div className="p-4 text-center text-gray-500">End of feed.</div>
      )}
      <button
        onClick={handleRefresh}
        disabled={isRefetching}
        className="sticky lg:bottom-6 bottom-24 ml-4 w-[42px] h-[42px] z-10 bg-gray-500 hover:bg-gray-600 text-gray-50 p-[9px] rounded-full shadow-lg transition-transform duration-200 ease-in-out hover:scale-110 disabled:bg-gray-400 disabled:cursor-not-allowed"
        aria-label="Refresh feed"
      >
        {isRefetching ? (
          <RefreshIcon className="h-6 w-6 animate-spin" />
        ) : (
          <RefreshIcon className="h-6 w-6" />
        )}
      </button>
    </>
  );
}

const RefreshIcon = (props: React.SVGProps<SVGSVGElement>) => (
  <svg
    xmlns="http://www.w3.org/2000/svg"
    //width={360}
    //height={360}
    viewBox="0 0 24 24"
    {...props}
  >
    <path
      fill="none"
      stroke="currentColor"
      strokeLinecap="round"
      strokeLinejoin="round"
      strokeWidth={2}
      d="M20 11A8.1 8.1 0 0 0 4.5 9M4 5v4h4m-4 4a8.1 8.1 0 0 0 15.5 2m.5 4v-4h-4"
    ></path>
  </svg>
);
