import { Fragment, jsx, jsxs } from "react/jsx-runtime";
import { useEffect, useMemo, useRef, useState } from "react";
import { Button, Typography, Stack, Alert, useTheme } from "@mui/material";
import { useLocaleContext } from "@arcblock/ux/lib/Locale/context";
import useArcblockBrowser from "@arcblock/react-hooks/lib/useBrowser";
import Toast from "@arcblock/ux/lib/Toast";
import { joinURL } from "ufo";
import { useRequest } from "ahooks";
import pWaitFor from "p-wait-for";
import Dialog from "@arcblock/ux/lib/Dialog/dialog";
import { CheckCircle as CheckCircleIcon } from "@mui/icons-material";
import debounce from "lodash/debounce";
import { usePaymentContext } from "../contexts/payment.js";
import { formatAmount, formatError, getPrefix, isCrossOrigin, primaryContrastColor } from "../libs/util.js";
import { useSubscription } from "../hooks/subscription.js";
import api from "../libs/api.js";
import LoadingButton from "./loading-button.js";
import StripePaymentAction from "./stripe-payment-action.js";
const fetchOverdueInvoices = async (params) => {
  if (!params.subscriptionId && !params.customerId) {
    throw new Error("Either subscriptionId or customerId must be provided");
  }
  let url;
  if (params.subscriptionId) {
    url = `/api/subscriptions/${params.subscriptionId}/overdue/invoices`;
  } else {
    url = `/api/customers/${params.customerId}/overdue/invoices`;
  }
  const res = await api.get(params.authToken ? joinURL(url, `?authToken=${params.authToken}`) : url);
  return res.data;
};
function OverdueInvoicePayment({
  subscriptionId = void 0,
  customerId = void 0,
  mode = "default",
  dialogProps = {
    open: true
  },
  children = void 0,
  onPaid = () => {
  },
  detailLinkOptions = { enabled: true },
  successToast = true,
  alertMessage = "",
  authToken = void 0
}) {
  const { t, locale } = useLocaleContext();
  const browser = useArcblockBrowser();
  const inArcSphere = browser?.arcSphere;
  const theme = useTheme();
  const { connect, session } = usePaymentContext();
  const [selectCurrencyId, setSelectCurrencyId] = useState("");
  const [payLoading, setPayLoading] = useState(false);
  const [dialogOpen, setDialogOpen] = useState(dialogProps.open || false);
  const [processedCurrencies, setProcessedCurrencies] = useState({});
  const [paymentStatus, setPaymentStatus] = useState(
    {}
  );
  const [stripePaymentInProgress, setStripePaymentInProgress] = useState({});
  const stripePaymentInProgressRef = useRef(stripePaymentInProgress);
  const sourceType = subscriptionId ? "subscription" : "customer";
  const effectiveCustomerId = customerId || session?.user?.did;
  const sourceId = subscriptionId || effectiveCustomerId;
  const customerIdRef = useRef(effectiveCustomerId);
  useEffect(() => {
    stripePaymentInProgressRef.current = stripePaymentInProgress;
  }, [stripePaymentInProgress]);
  const {
    data = {
      summary: {},
      invoices: []
    },
    error,
    loading,
    runAsync: refresh
  } = useRequest(() => fetchOverdueInvoices({ subscriptionId, customerId: effectiveCustomerId, authToken }), {
    ready: !!subscriptionId || !!effectiveCustomerId,
    onSuccess: (res) => {
      if (res.customer?.id && res.customer?.id !== customerIdRef.current) {
        customerIdRef.current = res.customer?.id;
      }
    }
  });
  const detailUrl = useMemo(() => {
    if (subscriptionId) {
      return joinURL(getPrefix(), `/customer/subscription/${subscriptionId}`);
    }
    if (effectiveCustomerId) {
      return joinURL(getPrefix(), "/customer/invoice/past-due");
    }
    return "";
  }, [subscriptionId, effectiveCustomerId]);
  const summaryList = useMemo(() => {
    if (!data?.summary) {
      return [];
    }
    return Object.values(data.summary);
  }, [data?.summary]);
  const checkAndHandleInvoicePaid = async (currencyId) => {
    if (stripePaymentInProgressRef.current[currencyId]) {
      try {
        const checkData = await fetchOverdueInvoices({
          subscriptionId,
          customerId: effectiveCustomerId,
          authToken
        });
        const hasRemainingInvoices = checkData.invoices?.some((inv) => inv.currency_id === currencyId);
        if (hasRemainingInvoices) {
          return;
        }
        setStripePaymentInProgress((prev) => {
          const newState = { ...prev };
          delete newState[currencyId];
          return newState;
        });
        setPaymentStatus((prev) => ({ ...prev, [currencyId]: "success" }));
      } catch (err) {
        console.error("Error checking Stripe payment completion:", err);
        return;
      }
    }
    if (successToast) {
      Toast.close();
      Toast.success(t("payment.customer.invoice.paySuccess"));
    }
    setPayLoading(false);
    const res = await refresh();
    if (res.invoices?.length === 0) {
      setDialogOpen(false);
      onPaid(sourceId, currencyId, sourceType);
    }
  };
  const debouncedHandleInvoicePaid = debounce((currencyId) => checkAndHandleInvoicePaid(currencyId), 1e3, {
    leading: false,
    trailing: true,
    maxWait: 5e3
  });
  const isCrossOriginRequest = isCrossOrigin();
  const subscription = useSubscription("events");
  const waitForInvoicePaidByCurrency = async (currencyId) => {
    let isPaid = false;
    await pWaitFor(
      async () => {
        const checkData = await fetchOverdueInvoices({
          subscriptionId,
          customerId: effectiveCustomerId,
          authToken
        });
        const hasRemainingInvoices = checkData.invoices?.some((inv) => inv.currency_id === currencyId);
        isPaid = !hasRemainingInvoices;
        return isPaid;
      },
      { interval: 2e3, timeout: 3 * 60 * 1e3 }
    );
    return isPaid;
  };
  const handleConnected = async (currencyId, isStripe = false) => {
    if (isCrossOriginRequest || inArcSphere) {
      try {
        const paid = await waitForInvoicePaidByCurrency(currencyId);
        if (paid) {
          setPaymentStatus((prev) => ({ ...prev, [currencyId]: "success" }));
          const finalRes = await refresh();
          if (successToast) {
            Toast.close();
            Toast.success(t("payment.customer.invoice.paySuccess"));
          }
          if (finalRes.invoices?.length === 0) {
            setDialogOpen(false);
            onPaid(sourceId, currencyId, sourceType);
          }
        }
      } catch (err) {
        console.error("Check payment status failed:", err);
        setPaymentStatus((prev) => ({ ...prev, [currencyId]: "error" }));
      } finally {
        setPayLoading(false);
      }
    } else if (isStripe) {
      setStripePaymentInProgress((prev) => ({ ...prev, [currencyId]: true }));
      setPaymentStatus((prev) => ({ ...prev, [currencyId]: "processing" }));
    }
  };
  useEffect(() => {
    if (!subscription || isCrossOriginRequest || inArcSphere) {
      return void 0;
    }
    const handleInvoicePaid = ({ response }) => {
      const relevantId = subscriptionId || response.customer_id;
      const uniqueKey = `${relevantId}-${response.currency_id}`;
      if (subscriptionId && response.subscription_id === subscriptionId || effectiveCustomerId && effectiveCustomerId === response.customer_id || customerIdRef.current && customerIdRef.current === response.customer_id) {
        if (!processedCurrencies[uniqueKey]) {
          setProcessedCurrencies((prev) => ({ ...prev, [uniqueKey]: 1 }));
          debouncedHandleInvoicePaid(response.currency_id);
        }
      }
    };
    subscription.on("invoice.paid", handleInvoicePaid);
    return () => {
      subscription.off("invoice.paid", handleInvoicePaid);
    };
  }, [subscription, subscriptionId, effectiveCustomerId]);
  const handlePay = (item) => {
    const { currency, method } = item;
    if (method.type === "stripe") {
      Toast.error(t("payment.subscription.overdue.notSupport"));
      return;
    }
    if (payLoading) {
      return;
    }
    setSelectCurrencyId(currency.id);
    setPayLoading(true);
    setPaymentStatus((prev) => ({
      ...prev,
      [currency.id]: "idle"
    }));
    if (["arcblock", "ethereum", "base"].includes(method.type)) {
      const extraParams = { currencyId: currency.id };
      if (subscriptionId) {
        extraParams.subscriptionId = subscriptionId;
      } else if (effectiveCustomerId) {
        extraParams.customerId = effectiveCustomerId;
      }
      connect.open({
        locale,
        containerEl: void 0,
        saveConnect: false,
        action: "collect-batch",
        prefix: joinURL(getPrefix(), "/api/did"),
        useSocket: !isCrossOriginRequest,
        extraParams,
        messages: {
          scan: t("common.connect.defaultScan"),
          title: t("payment.customer.invoice.payBatch"),
          confirm: t("common.connect.confirm")
        },
        onSuccess: () => {
          connect.close();
          handleConnected(currency.id);
          setPayLoading(false);
          setPaymentStatus((prev) => ({
            ...prev,
            [currency.id]: "success"
          }));
        },
        onClose: () => {
          connect.close();
          setPayLoading(false);
        },
        onError: (err) => {
          Toast.error(formatError(err));
          setPaymentStatus((prev) => ({
            ...prev,
            [currency.id]: "error"
          }));
          setPayLoading(false);
        }
      });
    }
  };
  const handleClose = () => {
    setDialogOpen(false);
    dialogProps.onClose?.();
  };
  const handleViewDetailClick = (e) => {
    if (detailLinkOptions.onClick) {
      e.preventDefault();
      detailLinkOptions.onClick(e);
    } else if (!detailLinkOptions.enabled) {
      e.preventDefault();
      handleClose();
    }
  };
  if (loading) {
    return null;
  }
  const getDetailLinkText = () => {
    if (detailLinkOptions.title) {
      return detailLinkOptions.title;
    }
    if (subscriptionId) {
      return t("payment.subscription.overdue.view");
    }
    return t("payment.customer.pastDue.view");
  };
  const renderPayButton = (item, primaryButton = true, options = {
    variant: "contained"
  }) => {
    const { currency } = item;
    const inProcess = payLoading && selectCurrencyId === currency.id;
    const status = paymentStatus[currency.id] || "idle";
    const containedColorSx = (options?.variant || "contained") === "contained" ? { color: (th) => primaryContrastColor(th) } : {};
    if (status === "success") {
      return /* @__PURE__ */ jsx(
        Button,
        {
          variant: options?.variant || "contained",
          size: "small",
          onClick: () => checkAndHandleInvoicePaid(currency.id),
          sx: containedColorSx,
          ...primaryButton ? {} : {
            color: "success",
            startIcon: /* @__PURE__ */ jsx(CheckCircleIcon, {})
          },
          children: t("payment.subscription.overdue.paid")
        }
      );
    }
    if (item.method.type === "stripe") {
      let buttonText = t("payment.subscription.overdue.payNow");
      if (status === "error") {
        buttonText = t("payment.subscription.overdue.retry");
      } else if (status === "processing") {
        buttonText = t("payment.subscription.overdue.processing");
      }
      return /* @__PURE__ */ jsx(
        StripePaymentAction,
        {
          subscriptionId,
          customerId: !subscriptionId ? effectiveCustomerId : void 0,
          currencyId: currency.id,
          paymentMethod: item.method,
          onSuccess: () => {
            handleConnected(currency.id, true);
          },
          onError: () => {
            setPaymentStatus((prev) => ({ ...prev, [currency.id]: "error" }));
            setStripePaymentInProgress((prev) => ({ ...prev, [currency.id]: false }));
          },
          children: (onPay, paying) => /* @__PURE__ */ jsx(
            LoadingButton,
            {
              variant: options?.variant || "contained",
              size: "small",
              disabled: paying || status === "processing",
              loading: paying || status === "processing",
              onClick: onPay,
              sx: { ...containedColorSx, ...options?.sx || {} },
              children: buttonText
            }
          )
        }
      );
    }
    return /* @__PURE__ */ jsx(
      LoadingButton,
      {
        variant: options?.variant || "contained",
        size: "small",
        disabled: inProcess,
        loading: inProcess,
        onClick: () => handlePay(item),
        sx: { ...containedColorSx, ...options?.sx || {} },
        children: status === "error" ? t("payment.subscription.overdue.retry") : t("payment.subscription.overdue.payNow")
      }
    );
  };
  const getMethodText = (method) => {
    if (method.name && method.type !== "arcblock") {
      return ` (${method.name})`;
    }
    return "";
  };
  const getOverdueTitle = () => {
    if (subscriptionId && data.subscription) {
      if (summaryList.length === 1) {
        return t("payment.subscription.overdue.title", {
          name: data.subscription?.description,
          count: data.invoices?.length,
          total: formatAmount(summaryList[0]?.amount, summaryList[0]?.currency?.decimal),
          symbol: summaryList[0]?.currency?.symbol,
          method: getMethodText(summaryList[0]?.method)
        });
      }
      return t("payment.subscription.overdue.simpleTitle", {
        name: data.subscription?.description,
        count: data.invoices?.length
      });
    }
    if (effectiveCustomerId) {
      let title = "";
      if (summaryList.length === 1) {
        title = t("payment.customer.overdue.title", {
          subscriptionCount: data.subscriptionCount || 0,
          count: data.invoices?.length,
          total: formatAmount(summaryList[0]?.amount, summaryList[0]?.currency?.decimal),
          symbol: summaryList[0]?.currency?.symbol,
          method: getMethodText(summaryList[0]?.method)
        });
      } else {
        title = t("payment.customer.overdue.simpleTitle", {
          subscriptionCount: data.subscriptionCount || 0,
          count: data.invoices?.length
        });
      }
      if (alertMessage) {
        return `${title}${alertMessage}`;
      }
      return `${title}${t("payment.customer.overdue.defaultAlert")}`;
    }
    return "";
  };
  const getEmptyStateMessage = () => {
    if (subscriptionId && data.subscription) {
      return t("payment.subscription.overdue.empty", {
        name: data.subscription?.description
      });
    }
    return t("payment.customer.overdue.empty");
  };
  if (mode === "custom" && children && typeof children === "function") {
    return /* @__PURE__ */ jsx(Stack, { children: children(handlePay, {
      subscription: data?.subscription,
      summary: data?.summary,
      invoices: data?.invoices,
      subscriptionCount: data?.subscriptionCount,
      detailUrl
    }) });
  }
  return /* @__PURE__ */ jsx(
    Dialog,
    {
      PaperProps: {
        style: { minHeight: "auto" }
      },
      ...dialogProps || {},
      open: dialogOpen,
      title: dialogProps?.title || t("payment.subscription.overdue.pastDue"),
      sx: { "& .MuiDialogContent-root": { pt: 0 } },
      onClose: handleClose,
      children: error ? /* @__PURE__ */ jsx(Alert, { severity: "error", children: error.message }) : /* @__PURE__ */ jsxs(
        Stack,
        {
          sx: {
            gap: 1
          },
          children: [
            summaryList.length === 0 && /* @__PURE__ */ jsxs(Fragment, { children: [
              /* @__PURE__ */ jsx(Alert, { severity: "success", children: getEmptyStateMessage() }),
              /* @__PURE__ */ jsx(
                Stack,
                {
                  direction: "row",
                  sx: {
                    justifyContent: "flex-end",
                    mt: 2
                  },
                  children: /* @__PURE__ */ jsx(Button, { variant: "outlined", color: "primary", onClick: handleClose, sx: { width: "fit-content" }, children: t("common.know") })
                }
              )
            ] }),
            summaryList.length === 1 && /* @__PURE__ */ jsxs(Fragment, { children: [
              /* @__PURE__ */ jsxs(
                Typography,
                {
                  variant: "body1",
                  sx: {
                    color: "text.secondary"
                  },
                  children: [
                    getOverdueTitle(),
                    detailLinkOptions.enabled && /* @__PURE__ */ jsxs(Fragment, { children: [
                      /* @__PURE__ */ jsx("br", {}),
                      t("payment.subscription.overdue.description"),
                      /* @__PURE__ */ jsx(
                        "a",
                        {
                          href: detailUrl,
                          target: "_blank",
                          onClick: handleViewDetailClick,
                          rel: "noreferrer",
                          style: { color: theme.palette.text.link },
                          children: getDetailLinkText()
                        }
                      )
                    ] })
                  ]
                }
              ),
              /* @__PURE__ */ jsxs(
                Stack,
                {
                  direction: "row",
                  sx: {
                    justifyContent: "flex-end",
                    gap: 2,
                    mt: 2
                  },
                  children: [
                    /* @__PURE__ */ jsx(Button, { variant: "outlined", color: "primary", onClick: handleClose, children: t("common.cancel") }),
                    renderPayButton(summaryList[0])
                  ]
                }
              )
            ] }),
            summaryList.length > 1 && /* @__PURE__ */ jsxs(Fragment, { children: [
              /* @__PURE__ */ jsxs(
                Typography,
                {
                  variant: "body1",
                  sx: {
                    color: "text.secondary"
                  },
                  children: [
                    getOverdueTitle(),
                    detailLinkOptions.enabled && /* @__PURE__ */ jsxs(Fragment, { children: [
                      /* @__PURE__ */ jsx("br", {}),
                      t("payment.subscription.overdue.description"),
                      /* @__PURE__ */ jsx(
                        "a",
                        {
                          href: detailUrl,
                          target: "_blank",
                          rel: "noreferrer",
                          onClick: handleViewDetailClick,
                          style: { color: theme.palette.text.link },
                          children: getDetailLinkText()
                        }
                      )
                    ] })
                  ]
                }
              ),
              /* @__PURE__ */ jsx(
                Typography,
                {
                  variant: "body1",
                  sx: {
                    color: "text.secondary"
                  },
                  children: t("payment.subscription.overdue.list")
                }
              ),
              /* @__PURE__ */ jsx(Stack, { children: summaryList.map((item) => /* @__PURE__ */ jsxs(
                Stack,
                {
                  direction: "row",
                  sx: {
                    justifyContent: "space-between",
                    alignItems: "center",
                    py: 1,
                    px: 0.5,
                    borderBottom: "1px solid",
                    borderColor: "divider",
                    "&:hover": {
                      backgroundColor: () => theme.palette.grey[100]
                    },
                    mt: 0
                  },
                  children: [
                    /* @__PURE__ */ jsx(Typography, { children: t("payment.subscription.overdue.total", {
                      total: formatAmount(item?.amount, item?.currency?.decimal),
                      currency: item?.currency?.symbol,
                      method: getMethodText(item?.method)
                    }) }),
                    renderPayButton(item, false, {
                      variant: "text",
                      sx: {
                        color: "text.link"
                      }
                    })
                  ]
                },
                item?.currency?.id
              )) })
            ] })
          ]
        }
      )
    }
  );
}
export default OverdueInvoicePayment;
