"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});

var _jsxRuntime = require("react/jsx-runtime");
var _react = require("react");
var _material = require("@mui/material");
var _context = require("@arcblock/ux/lib/Locale/context");
var _useBrowser = _interopRequireDefault(require("@arcblock/react-hooks/lib/useBrowser"));
var _Toast = _interopRequireDefault(require("@arcblock/ux/lib/Toast"));
var _ufo = require("ufo");
var _ahooks = require("ahooks");
var _pWaitFor = _interopRequireDefault(require("p-wait-for"));
var _dialog = _interopRequireDefault(require("@arcblock/ux/lib/Dialog/dialog"));
var _iconsMaterial = require("@mui/icons-material");
var _debounce = _interopRequireDefault(require("lodash/debounce"));
var _payment = require("../contexts/payment");
var _util = require("../libs/util");
var _subscription = require("../hooks/subscription");
var _api = _interopRequireDefault(require("../libs/api"));
var _loadingButton = _interopRequireDefault(require("./loading-button"));
var _stripePaymentAction = _interopRequireDefault(require("./stripe-payment-action"));
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
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.default.get(params.authToken ? (0, _ufo.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
  } = (0, _context.useLocaleContext)();
  const browser = (0, _useBrowser.default)();
  const inArcSphere = browser?.arcSphere;
  const theme = (0, _material.useTheme)();
  const {
    connect,
    session
  } = (0, _payment.usePaymentContext)();
  const [selectCurrencyId, setSelectCurrencyId] = (0, _react.useState)("");
  const [payLoading, setPayLoading] = (0, _react.useState)(false);
  const [dialogOpen, setDialogOpen] = (0, _react.useState)(dialogProps.open || false);
  const [processedCurrencies, setProcessedCurrencies] = (0, _react.useState)({});
  const [paymentStatus, setPaymentStatus] = (0, _react.useState)({});
  const [stripePaymentInProgress, setStripePaymentInProgress] = (0, _react.useState)({});
  const stripePaymentInProgressRef = (0, _react.useRef)(stripePaymentInProgress);
  const sourceType = subscriptionId ? "subscription" : "customer";
  const effectiveCustomerId = customerId || session?.user?.did;
  const sourceId = subscriptionId || effectiveCustomerId;
  const customerIdRef = (0, _react.useRef)(effectiveCustomerId);
  (0, _react.useEffect)(() => {
    stripePaymentInProgressRef.current = stripePaymentInProgress;
  }, [stripePaymentInProgress]);
  const {
    data = {
      summary: {},
      invoices: []
    },
    error,
    loading,
    runAsync: refresh
  } = (0, _ahooks.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 = (0, _react.useMemo)(() => {
    if (subscriptionId) {
      return (0, _ufo.joinURL)((0, _util.getPrefix)(), `/customer/subscription/${subscriptionId}`);
    }
    if (effectiveCustomerId) {
      return (0, _ufo.joinURL)((0, _util.getPrefix)(), "/customer/invoice/past-due");
    }
    return "";
  }, [subscriptionId, effectiveCustomerId]);
  const summaryList = (0, _react.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.default.close();
      _Toast.default.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 = (0, _debounce.default)(currencyId => checkAndHandleInvoicePaid(currencyId), 1e3, {
    leading: false,
    trailing: true,
    maxWait: 5e3
  });
  const isCrossOriginRequest = (0, _util.isCrossOrigin)();
  const subscription = (0, _subscription.useSubscription)("events");
  const waitForInvoicePaidByCurrency = async currencyId => {
    let isPaid = false;
    await (0, _pWaitFor.default)(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.default.close();
            _Toast.default.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"
      }));
    }
  };
  (0, _react.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.default.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: (0, _ufo.joinURL)((0, _util.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.default.error((0, _util.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 => (0, _util.primaryContrastColor)(th)
    } : {};
    if (status === "success") {
      return /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Button, {
        variant: options?.variant || "contained",
        size: "small",
        onClick: () => checkAndHandleInvoicePaid(currency.id),
        sx: containedColorSx,
        ...(primaryButton ? {} : {
          color: "success",
          startIcon: /* @__PURE__ */(0, _jsxRuntime.jsx)(_iconsMaterial.CheckCircle, {})
        }),
        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__ */(0, _jsxRuntime.jsx)(_stripePaymentAction.default, {
        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__ */(0, _jsxRuntime.jsx)(_loadingButton.default, {
          variant: options?.variant || "contained",
          size: "small",
          disabled: paying || status === "processing",
          loading: paying || status === "processing",
          onClick: onPay,
          sx: {
            ...containedColorSx,
            ...(options?.sx || {})
          },
          children: buttonText
        })
      });
    }
    return /* @__PURE__ */(0, _jsxRuntime.jsx)(_loadingButton.default, {
      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: (0, _util.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: (0, _util.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__ */(0, _jsxRuntime.jsx)(_material.Stack, {
      children: children(handlePay, {
        subscription: data?.subscription,
        summary: data?.summary,
        invoices: data?.invoices,
        subscriptionCount: data?.subscriptionCount,
        detailUrl
      })
    });
  }
  return /* @__PURE__ */(0, _jsxRuntime.jsx)(_dialog.default, {
    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__ */(0, _jsxRuntime.jsx)(_material.Alert, {
      severity: "error",
      children: error.message
    }) : /* @__PURE__ */(0, _jsxRuntime.jsxs)(_material.Stack, {
      sx: {
        gap: 1
      },
      children: [summaryList.length === 0 && /* @__PURE__ */(0, _jsxRuntime.jsxs)(_jsxRuntime.Fragment, {
        children: [/* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Alert, {
          severity: "success",
          children: getEmptyStateMessage()
        }), /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Stack, {
          direction: "row",
          sx: {
            justifyContent: "flex-end",
            mt: 2
          },
          children: /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Button, {
            variant: "outlined",
            color: "primary",
            onClick: handleClose,
            sx: {
              width: "fit-content"
            },
            children: t("common.know")
          })
        })]
      }), summaryList.length === 1 && /* @__PURE__ */(0, _jsxRuntime.jsxs)(_jsxRuntime.Fragment, {
        children: [/* @__PURE__ */(0, _jsxRuntime.jsxs)(_material.Typography, {
          variant: "body1",
          sx: {
            color: "text.secondary"
          },
          children: [getOverdueTitle(), detailLinkOptions.enabled && /* @__PURE__ */(0, _jsxRuntime.jsxs)(_jsxRuntime.Fragment, {
            children: [/* @__PURE__ */(0, _jsxRuntime.jsx)("br", {}), t("payment.subscription.overdue.description"), /* @__PURE__ */(0, _jsxRuntime.jsx)("a", {
              href: detailUrl,
              target: "_blank",
              onClick: handleViewDetailClick,
              rel: "noreferrer",
              style: {
                color: theme.palette.text.link
              },
              children: getDetailLinkText()
            })]
          })]
        }), /* @__PURE__ */(0, _jsxRuntime.jsxs)(_material.Stack, {
          direction: "row",
          sx: {
            justifyContent: "flex-end",
            gap: 2,
            mt: 2
          },
          children: [/* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Button, {
            variant: "outlined",
            color: "primary",
            onClick: handleClose,
            children: t("common.cancel")
          }), renderPayButton(summaryList[0])]
        })]
      }), summaryList.length > 1 && /* @__PURE__ */(0, _jsxRuntime.jsxs)(_jsxRuntime.Fragment, {
        children: [/* @__PURE__ */(0, _jsxRuntime.jsxs)(_material.Typography, {
          variant: "body1",
          sx: {
            color: "text.secondary"
          },
          children: [getOverdueTitle(), detailLinkOptions.enabled && /* @__PURE__ */(0, _jsxRuntime.jsxs)(_jsxRuntime.Fragment, {
            children: [/* @__PURE__ */(0, _jsxRuntime.jsx)("br", {}), t("payment.subscription.overdue.description"), /* @__PURE__ */(0, _jsxRuntime.jsx)("a", {
              href: detailUrl,
              target: "_blank",
              rel: "noreferrer",
              onClick: handleViewDetailClick,
              style: {
                color: theme.palette.text.link
              },
              children: getDetailLinkText()
            })]
          })]
        }), /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Typography, {
          variant: "body1",
          sx: {
            color: "text.secondary"
          },
          children: t("payment.subscription.overdue.list")
        }), /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Stack, {
          children: summaryList.map(item => /* @__PURE__ */(0, _jsxRuntime.jsxs)(_material.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__ */(0, _jsxRuntime.jsx)(_material.Typography, {
              children: t("payment.subscription.overdue.total", {
                total: (0, _util.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))
        })]
      })]
    })
  });
}
module.exports = OverdueInvoicePayment;