"use client";

import { useCallback, useEffect, useMemo, useState } from "react";
import { Data } from "@lottiefiles/dotlottie-react";

import indexedDB, { EObjectStores } from "@/shared/utils/indexedDB";
import { ELottieKeys, lottieUrls } from "@/shared/constants/lottie";

interface IUseLottieProps {
  preloadKey?: ELottieKeys;
  loadKey?: ELottieKeys;
}

export const useLottie = ({ preloadKey, loadKey }: IUseLottieProps) => {
  const [animationData, setAnimationData] = useState<Data>();
  const [isError, setIsError] = useState(false);
  const [isLoading, setIsLoading] = useState(false);

  const getAnimationDataFromLottie = async (key: ELottieKeys) => {
    try {
      const animation = await fetch(lottieUrls[key]);
      if (!animation.ok) {
        throw new Error(`HTTP error! status: ${animation.status}`);
      }
      const arrayBuffer = await animation.arrayBuffer();
      return arrayBuffer;
    } catch (error) {
      console.error("Error loading animation:", error);
      setIsError(true);
      return null;
    }
  };

  const preload = useCallback(async (key: ELottieKeys) => {
    console.log("preload", key);

    const arrayBuffer = await getAnimationDataFromLottie(key);
    indexedDB.set(EObjectStores.Lottie, key, arrayBuffer);
  }, []);

  const load = useCallback(async (key: ELottieKeys) => {
    setIsLoading(true);
    setIsError(false);
    try {
      const animationFromDB = await indexedDB.get<ArrayBuffer>(
        EObjectStores.Lottie,
        key
      );
      if (animationFromDB) {
        setAnimationData(animationFromDB);
        setIsLoading(false);
        return;
      }

      const arrayBuffer = await getAnimationDataFromLottie(key);
      if (!arrayBuffer) {
        setIsLoading(false);
        return;
      }

      setAnimationData(arrayBuffer);
      await indexedDB.set<ArrayBuffer>(EObjectStores.Lottie, key, arrayBuffer);
    } catch (error) {
      console.error("Error in load process:", error);
      setIsError(true);
    } finally {
      setIsLoading(false);
    }
  }, []);

  useEffect(() => {
    if (preloadKey) {
      preload(preloadKey);
    }
    if (loadKey) {
      load(loadKey);
    }
  }, [load, loadKey, preload, preloadKey]);

  return useMemo(
    () => ({
      animationData,
      isError,
      isLoading,
    }),
    [animationData, isError, isLoading]
  );
};
