import { useApi } from "@/api";
import { EPlacementKeys, IPaywall } from "@/api/resources/Paywall";
import { actions, selectors } from "@/store";
import { useCallback, useEffect, useMemo, useState } from "react";
import { useDispatch, useSelector } from "react-redux";
import parse from "html-react-parser";
import { defaultPaywalls } from "./defaultPaywalls";

interface IUsePaywallProps {
  placementKey: EPlacementKeys;
}

interface IGetTextProps {
  replacementSelector?: string;
  color?: string;
  replacement?: {
    target: string;
    replacement: string;
  };
}

export function usePaywall({ placementKey }: IUsePaywallProps) {
  const api = useApi();
  const dispatch = useDispatch();
  const token = useSelector(selectors.selectToken);
  const [paywall, setPaywall] = useState<IPaywall>();
  const [isLoading, setIsLoading] = useState(false);
  const [error, setError] = useState(false);
  const products = useMemo(() => paywall?.products || [], [paywall?.products]);
  const properties = useMemo(
    () => paywall?.properties || [],
    [paywall?.properties]
  );
  const isMustUpdate = useSelector(selectors.selectPaywallsIsMustUpdate);
  const paywalls = useSelector(selectors.selectPaywalls);

  const getPaywallByPlacementKey = useCallback(
    async (placementKey: EPlacementKeys) => {
      try {
        setIsLoading(true);
        setError(false);
        const paywall = await api.getPaywallByPlacementKey({
          placementKey,
          token,
        });
        if ("paywall" in paywall && paywall.paywall) {
          setPaywall(paywall.paywall);
          dispatch(
            actions.paywalls.updatePaywall({
              [placementKey]: paywall.paywall,
            })
          );
          dispatch(
            actions.paywalls.updateIsMustUpdate({
              [placementKey]: false,
            })
          );
        }
      } catch (error) {
        console.error(error);
        setError(true);
        setPaywall(defaultPaywalls[placementKey]);
      } finally {
        setIsLoading(false);
      }
    },
    [api, dispatch, token]
  );

  useEffect(() => {
    if (isMustUpdate[placementKey] || !paywalls[placementKey]) {
      getPaywallByPlacementKey(placementKey);
    } else {
      // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
      setPaywall(paywalls[placementKey]!);
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [getPaywallByPlacementKey, placementKey, isMustUpdate]);

  const getText = useCallback(
    (
      key: string,
      {
        replacementSelector = "span",
        color = "inherit",
        replacement,
      }: IGetTextProps
    ) => {
      const property = properties.find((property) => property.key === key);
      if (!property) return "";
      const text = property.value;
      const colorElements = properties.filter((property) =>
        property.key.includes(`${key}.color`)
      );
      if (text && colorElements.length) {
        let element = text;
        for (const colorElement of colorElements) {
          element = element.replace(
            colorElement.value,
            `<${replacementSelector} class="${property.key}" style="color: ${color}">${colorElement.value}</${replacementSelector}>`
          );
        }
        return parse(element);
      }
      if (text && replacement) {
        return text.replace(replacement.target, replacement.replacement);
      }
      return text;
    },
    [properties]
  );

  return useMemo(
    () => ({
      paywall,
      isLoading,
      error,
      products,
      properties,
      getText,
    }),
    [error, isLoading, paywall, products, properties, getText]
  );
}
