import React, { useEffect } from "react";

import { useZappPipesFeed } from "@applicaster/zapp-react-native-redux";

import { reactHooksLogger } from "../logger";
import { shouldDispatchData, useIsInitialRender } from "../utils";
import { useInflatedUrl } from "./useInflatedUrl";
import { useLoadPipesDataDispatch } from "./useLoadPipesDataDispatch";

const logger = reactHooksLogger.addSubsystem("useFeedLoader");

type Props = {
  feedUrl: string | null;
  mapping?: ZappTypeMapping;
  pipesOptions?: {
    clearCache?: boolean;
    loadLocalFavourites?: boolean;
    silentRefresh?: boolean;
    method?: "get" | "post";
    bodyParams?: Record<string, unknown>;
    skipLoading?: boolean;
  };
};

export type ReloadDataFunction = (
  silentRefresh?: boolean,
  callback?: (data: any, error?: any) => void
) => void;

type FeedLoaderResponse = PipesDataObject & {
  loadNext?: () => void;
  reloadData?: ReloadDataFunction;
};

export const useFeedLoader = ({
  feedUrl,
  mapping,
  pipesOptions = {},
}: Props): FeedLoaderResponse => {
  const isInitialRender = useIsInitialRender();

  const callableFeedUrl = useInflatedUrl({ feedUrl, mapping });

  const currentFeed = useZappPipesFeed(callableFeedUrl);

  const loadPipesDataDispatcher = useLoadPipesDataDispatch();

  const reloadData = React.useCallback<ReloadDataFunction>(
    (silentRefresh = true, callback) => {
      loadPipesDataDispatcher(
        callableFeedUrl,
        {
          clearCache: true,
          silentRefresh,
          callback,
        },
        {
          withResolvers: true,
        }
      );
    },
    [callableFeedUrl]
  );

  const loadNext: FeedLoaderResponse["loadNext"] = React.useCallback(() => {
    if (callableFeedUrl) {
      const nextFeed = currentFeed?.data?.next;

      loadPipesDataDispatcher(
        nextFeed,
        {
          silentRefresh: true,
          parentFeed: callableFeedUrl,
        },
        {
          withResolvers: true,
        }
      );
    }
  }, [callableFeedUrl, currentFeed?.data?.next]);

  useEffect(() => {
    if (
      shouldDispatchData(callableFeedUrl, currentFeed, pipesOptions.clearCache)
    ) {
      if (callableFeedUrl && !pipesOptions.skipLoading) {
        loadPipesDataDispatcher(
          callableFeedUrl,
          {
            ...pipesOptions,
            clearCache: true,
          },
          {
            withResolvers: true,
            withScreenRouteMapping: true,
          }
        );
      } else if (!callableFeedUrl) {
        logger.info({
          message:
            "Feed is not defined or not inflated, skipping loading. \nMake sure you have correct feedUrl and mapping.",
          jsOnly: true,
        });
      } else {
        logger.info({
          message:
            "Loading skipped as per pipesOptions.skipLoading configuration.",
          data: { url: callableFeedUrl },
          jsOnly: true,
        });
      }
    } else {
      logger.info({
        message:
          "Feed already exists, skipping loading. \nCall reloadData() if you want to refresh data.",
        data: { url: callableFeedUrl },
        jsOnly: true,
      });
    }
  }, []);

  // Reload feed when feedUrl changes, unless skipLoading is true
  useEffect(() => {
    if (!isInitialRender && callableFeedUrl && !pipesOptions.skipLoading) {
      loadPipesDataDispatcher(callableFeedUrl, pipesOptions, {
        withResolvers: true,
      });
    }
  }, [callableFeedUrl, isInitialRender, pipesOptions.skipLoading]);

  return React.useMemo(() => {
    if (!callableFeedUrl || !feedUrl) {
      return {
        error: new Error("No Feed url provided"),
        loading: false,
        url: "", // empty string when no data
        data: null,
      };
    }

    if (!currentFeed) {
      return {
        loading: true,
        url: callableFeedUrl || feedUrl,
        data: null,
      };
    }

    return {
      error: currentFeed?.error,
      loading: currentFeed?.loading,
      url: currentFeed?.url,
      data: currentFeed?.data,
      reloadData,
      loadNext,
    };
  }, [
    callableFeedUrl,
    currentFeed?.data,
    currentFeed?.error,
    currentFeed?.loading,
    reloadData,
    loadNext,
  ]);
};
