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";
import locales from "@/locales/locales";
import {
  ELocalesPlacement,
  getDefaultLocaleByLanguage,
  language,
} from "@/locales";
import { useTranslations } from "@/hooks/translations";
import { Currency } from "@/components/PaymentTable";

interface IUsePaywallProps {
  placementKey: EPlacementKeys;
  localesPlacement?: ELocalesPlacement;
}

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

export function usePaywall({
  placementKey,
  localesPlacement = ELocalesPlacement.V0,
}: IUsePaywallProps) {
  const locale = language;
  const { translate } = useTranslations(localesPlacement);
  const api = useApi();
  const dispatch = useDispatch();
  const token = useSelector(selectors.selectToken);
  const [paywall, setPaywall] = useState<IPaywall>();
  const currency = useSelector(selectors.selectCurrency);
  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 [placementId, setPlacementId] = useState<string>("");
  const [paywallId, setPaywallId] = useState<string>("");

  const getPaywallByPlacementKey = useCallback(
    async (placementKey: EPlacementKeys) => {
      try {
        setIsLoading(true);
        setError(false);
        const paywall = await api.getPaywallByPlacementKey({
          placementKey,
          token,
        });
        if ("paywall" in paywall && paywall.paywall) {
          if (paywall?.currency?.length) {
            dispatch(
              actions.userConfig.setCurrency(paywall.currency as Currency)
            );
          }
          setPaywall(paywall.paywall);
          setPaywallId(paywall.paywallId || "");
          setPlacementId(paywall.placementId || "");
          dispatch(
            actions.paywalls.updatePaywall({
              [placementKey]: 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]?.paywall) {
      getPaywallByPlacementKey(placementKey);
    } else {
      setPaywall(paywalls[placementKey]?.paywall);
      setPaywallId(paywalls[placementKey]?.paywallId || "");
      setPlacementId(paywalls[placementKey]?.placementId || "");
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [getPaywallByPlacementKey, placementKey, isMustUpdate]);

  const getText = useCallback(
    (key: string, options?: IGetTextProps) => {
      const {
        replacementSelector = "span",
        color = "inherit",
        replacement,
      } = options || {};
      const property = properties.find((property) => property.key === key);
      if (!property) return "";
      let text = property.value;
      if (getDefaultLocaleByLanguage(locale) in locales) {
        text = `${paywall?.key.replaceAll(".", "_")}.${key.replaceAll(
          ".",
          "_"
        )}`;
        if (translate(text) === text) {
          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) {
          let replacementValue = colorElement.value;
          if (locale in locales) {
            replacementValue = `${paywall?.key.replaceAll(
              ".",
              "_"
            )}.${colorElement.key.replaceAll(".", "_")}`;

            element = `${paywall?.key.replaceAll(".", "_")}.${key.replaceAll(
              ".",
              "_"
            )}`;
            if (translate(replacementValue) === replacementValue) {
              replacementValue = colorElement.value;
              element = text;
            }
          }
          element = translate(element).replace(
            colorElement.value,
            `<${replacementSelector} class="${
              property.key
            }" style="color: ${color}">${translate(
              replacementValue
            )}</${replacementSelector}>`
          );
        }
        return parse(element);
      }
      if (text && replacement?.length) {
        return replacement.reduce((acc, _replacement) => {
          return acc.replace(_replacement.target, _replacement.replacement);
        }, translate(text));
      }
      return translate(text);
    },
    [locale, paywall?.key, properties, translate]
  );

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