import { Fragment, jsx, jsxs } from "react/jsx-runtime";
import { useLocaleContext } from "@arcblock/ux/lib/Locale/context";
import Toast from "@arcblock/ux/lib/Toast";
import { HelpOutline } from "@mui/icons-material";
import { Box, Divider, Fade, Grow, Stack, Tooltip, Typography, Collapse, IconButton } from "@mui/material";
import { BN, fromTokenToUnit, fromUnitToToken } from "@ocap/util";
import { useRequest, useSetState } from "ahooks";
import noop from "lodash/noop";
import useBus from "use-bus";
import ExpandMoreIcon from "@mui/icons-material/ExpandMore";
import { styled } from "@mui/material/styles";
import { useEffect, useMemo, useRef } from "react";
import Status from "../components/status.js";
import api from "../libs/api.js";
import {
  formatAmount,
  formatCheckoutHeadlines,
  getPriceUintAmountByCurrency,
  formatDynamicPrice,
  findCurrency,
  formatError
} from "../libs/util.js";
import ProductDonation from "./product-donation.js";
import ProductItem from "./product-item.js";
import Livemode from "../components/livemode.js";
import { usePaymentContext } from "../contexts/payment.js";
import { useMobile } from "../hooks/mobile.js";
import { useDynamicPricing } from "../hooks/dynamic-pricing.js";
import LoadingButton from "../components/loading-button.js";
import DynamicPricingUnavailable from "../components/dynamic-pricing-unavailable.js";
import PromotionSection from "./summary-section/promotion-section.js";
import TotalSection from "./summary-section/total-section.js";
const ExpandMore = styled((props) => {
  const { expand, ...other } = props;
  return /* @__PURE__ */ jsx(IconButton, { ...other });
})(({ theme, expand }) => ({
  transform: !expand ? "rotate(0deg)" : "rotate(180deg)",
  marginLeft: "auto",
  transition: theme.transitions.create("transform", {
    duration: theme.transitions.duration.shortest
  })
}));
async function fetchCrossSell(id, skipError = true) {
  try {
    const { data } = await api.get(`/api/checkout-sessions/${id}/cross-sell?skipError=${skipError}`);
    if (!data.error) {
      return data;
    }
    return null;
  } catch (err) {
    return null;
  }
}
function getStakingSetup(items, currency, billingThreshold = 0) {
  const staking = {
    licensed: new BN(0),
    metered: new BN(0)
  };
  const recurringItems = items.map((x) => x.upsell_price || x.price).filter((x) => x.type === "recurring" && x.recurring);
  if (recurringItems.length > 0) {
    if (+billingThreshold) {
      return fromTokenToUnit(billingThreshold, currency.decimal).toString();
    }
    items.forEach((x) => {
      const price = x.upsell_price || x.price;
      const unit = getPriceUintAmountByCurrency(price, currency);
      const amount = new BN(unit).mul(new BN(x.quantity));
      if (price.type === "recurring" && price.recurring) {
        if (price.recurring.usage_type === "licensed") {
          staking.licensed = staking.licensed.add(amount);
        }
        if (price.recurring.usage_type === "metered") {
          staking.metered = staking.metered.add(amount);
        }
      }
    });
    return staking.licensed.add(staking.metered).toString();
  }
  return "0";
}
export default function PaymentSummary({
  items,
  currency,
  trialInDays,
  billingThreshold,
  onUpsell = noop,
  onDownsell = noop,
  onQuantityChange = noop,
  onApplyCrossSell = noop,
  onCancelCrossSell = noop,
  onChangeAmount = noop,
  checkoutSessionId = "",
  crossSellBehavior = "",
  showStaking = false,
  donationSettings = void 0,
  action = "",
  trialEnd = 0,
  completed = false,
  checkoutSession = void 0,
  paymentIntent = void 0,
  paymentMethods = [],
  onPromotionUpdate = noop,
  showFeatures = false,
  rateUnavailable = false,
  isRateLoading = false,
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
  rateError: _rateError = void 0,
  // Technical errors are logged but not displayed to users
  onQuoteExpired = void 0,
  onRefreshRate = void 0,
  onSlippageChange = void 0,
  slippageConfig: slippageConfigProp = void 0,
  liveRate = void 0,
  liveQuoteSnapshot = void 0,
  isStripePayment = false,
  isSubscription: isSubscriptionProp = void 0,
  ...rest
}) {
  const { t, locale } = useLocaleContext();
  const { isMobile } = useMobile();
  const { paymentState, ...settings } = usePaymentContext();
  const [state, setState] = useSetState({ loading: false, shake: false, expanded: items?.length < 3 });
  const { data, runAsync } = useRequest(
    (skipError) => checkoutSessionId ? fetchCrossSell(checkoutSessionId, skipError) : Promise.resolve(null)
  );
  const sessionDiscounts = checkoutSession?.discounts || [];
  const allowPromotionCodes = !!checkoutSession?.allow_promotion_codes;
  const hasDiscounts = sessionDiscounts?.length > 0;
  const discountCurrency = paymentMethods && checkoutSession ? findCurrency(
    paymentMethods,
    hasDiscounts ? checkoutSession?.currency_id || currency.id : currency.id
  ) || settings.settings?.baseCurrency : currency;
  const slippageConfig = slippageConfigProp ?? checkoutSession?.metadata?.slippage;
  const {
    hasDynamicPricing,
    isPriceLocked,
    quoteMeta,
    rateInfo,
    quoteLockedAt,
    currentSlippagePercent,
    rateDisplay,
    calculatedTokenAmount,
    calculatedDiscountAmount,
    calculateUsdDisplay,
    buildQuoteDetailRows
  } = useDynamicPricing({
    items,
    currency: discountCurrency,
    liveRate,
    liveQuoteSnapshot,
    checkoutSession,
    paymentIntent,
    locale,
    isStripePayment,
    isSubscription: isSubscriptionProp,
    slippageConfig,
    trialInDays,
    trialEnd,
    discounts: sessionDiscounts
  });
  const headlines = formatCheckoutHeadlines(items, discountCurrency, { trialEnd, trialInDays }, locale, {
    exchangeRate: rateInfo.exchangeRate
  });
  const staking = showStaking ? getStakingSetup(items, discountCurrency, billingThreshold) : "0";
  const effectiveHasDynamicPricing = hasDynamicPricing && !isStripePayment;
  const hasRecurringItems = items.some((x) => (x.upsell_price || x.price)?.type === "recurring");
  const isTrialScenario = headlines.actualAmount === "0" && hasRecurringItems;
  const headlineAmountDisplay = useMemo(() => {
    if (!effectiveHasDynamicPricing) {
      return headlines.amount;
    }
    if (isTrialScenario || !headlines.amount.includes(discountCurrency.symbol)) {
      return headlines.amount;
    }
    if (calculatedTokenAmount) {
      const displayAmount = fromUnitToToken(calculatedTokenAmount, discountCurrency?.decimal);
      const formatted2 = formatDynamicPrice(displayAmount, true, 6);
      return `${formatted2} ${discountCurrency.symbol}`;
    }
    const formatted = formatDynamicPrice(headlines.actualAmount, true, 6);
    return `${formatted} ${discountCurrency.symbol}`;
  }, [
    headlines.amount,
    headlines.actualAmount,
    discountCurrency.symbol,
    discountCurrency?.decimal,
    effectiveHasDynamicPricing,
    calculatedTokenAmount,
    isTrialScenario
  ]);
  const discountAmount = useMemo(
    () => new BN(checkoutSession?.total_details?.amount_discount || "0"),
    [checkoutSession?.total_details?.amount_discount]
  );
  const subtotalAmountUnit = new BN(fromTokenToUnit(headlines.actualAmount, discountCurrency?.decimal)).add(new BN(staking)).toString();
  const subtotalAmount = fromUnitToToken(subtotalAmountUnit, discountCurrency?.decimal);
  const totalAmountUnit = new BN(subtotalAmountUnit).sub(discountAmount).toString();
  const totalAmountValue = fromUnitToToken(totalAmountUnit, discountCurrency?.decimal);
  const subtotalDisplay = useMemo(() => {
    if (effectiveHasDynamicPricing && calculatedTokenAmount && !isTrialScenario) {
      const dynamicSubtotalUnit = new BN(calculatedTokenAmount).add(new BN(staking)).toString();
      const displayAmount = fromUnitToToken(dynamicSubtotalUnit, discountCurrency?.decimal);
      return formatDynamicPrice(displayAmount, true, 6);
    }
    return formatDynamicPrice(subtotalAmount, effectiveHasDynamicPricing, 6);
  }, [
    effectiveHasDynamicPricing,
    calculatedTokenAmount,
    staking,
    discountCurrency?.decimal,
    subtotalAmount,
    isTrialScenario
  ]);
  const totalAmountDisplay = useMemo(() => {
    if (effectiveHasDynamicPricing && calculatedTokenAmount && !isTrialScenario) {
      const effectiveDiscount = calculatedDiscountAmount ? new BN(calculatedDiscountAmount) : discountAmount;
      const dynamicTotalUnit = new BN(calculatedTokenAmount).add(new BN(staking)).sub(effectiveDiscount).toString();
      const displayAmount = fromUnitToToken(dynamicTotalUnit, discountCurrency?.decimal);
      const numericValue = Number(displayAmount);
      if (Number.isFinite(numericValue) && numericValue >= 0) {
        return formatDynamicPrice(displayAmount, true, 6);
      }
    }
    if (isStripePayment && calculatedDiscountAmount && !isTrialScenario) {
      const effectiveDiscount = new BN(calculatedDiscountAmount);
      const adjustedTotalUnit = new BN(subtotalAmountUnit).sub(effectiveDiscount).toString();
      const displayAmount = fromUnitToToken(adjustedTotalUnit, discountCurrency?.decimal);
      const numericValue = Number(displayAmount);
      if (Number.isFinite(numericValue) && numericValue >= 0) {
        return formatDynamicPrice(displayAmount, false, 6);
      }
    }
    return formatDynamicPrice(totalAmountValue, effectiveHasDynamicPricing, 6);
  }, [
    effectiveHasDynamicPricing,
    calculatedTokenAmount,
    staking,
    discountAmount,
    calculatedDiscountAmount,
    discountCurrency?.decimal,
    totalAmountValue,
    isTrialScenario,
    isStripePayment,
    subtotalAmountUnit
  ]);
  const totalAmountText = totalAmountDisplay === "\u2014" ? "\u2014" : `${totalAmountDisplay} ${discountCurrency.symbol}`;
  const totalUsdDisplay = useMemo(() => {
    if (effectiveHasDynamicPricing && calculatedTokenAmount && !isTrialScenario) {
      const effectiveDiscount = calculatedDiscountAmount ? new BN(calculatedDiscountAmount) : discountAmount;
      const dynamicTotalUnit = new BN(calculatedTokenAmount).add(new BN(staking)).sub(effectiveDiscount).toString();
      const dynamicTotalToken = fromUnitToToken(dynamicTotalUnit, discountCurrency?.decimal);
      return calculateUsdDisplay(dynamicTotalToken);
    }
    return calculateUsdDisplay(totalAmountValue);
  }, [
    effectiveHasDynamicPricing,
    calculatedTokenAmount,
    staking,
    discountAmount,
    calculatedDiscountAmount,
    discountCurrency?.decimal,
    totalAmountValue,
    calculateUsdDisplay,
    isTrialScenario
  ]);
  const quoteDetailRows = buildQuoteDetailRows(t);
  const isSubscription = isSubscriptionProp ?? (checkoutSession?.mode === "subscription" || checkoutSession?.mode === "setup");
  const handlePromotionUpdate = () => {
    onPromotionUpdate?.();
  };
  const handleRemovePromotion = async (sessionId) => {
    if (paymentState.paying || paymentState.stripePaying) {
      return;
    }
    try {
      await api.delete(`/api/checkout-sessions/${sessionId}/remove-promotion`);
      onPromotionUpdate?.();
    } catch (err) {
      console.error("Failed to remove promotion code:", err);
    }
  };
  const expiredHandledRef = useRef(false);
  useEffect(() => {
    if (completed || expiredHandledRef.current) {
      return;
    }
    if (!liveQuoteSnapshot?.expires_at && !quoteMeta?.expiresAt) {
      return;
    }
    const currentTime = Math.floor(Date.now() / 1e3);
    const effectiveExpiresAt = liveQuoteSnapshot?.expires_at ?? quoteMeta?.expiresAt;
    const quoteRemaining = effectiveExpiresAt ? Math.max(0, effectiveExpiresAt - currentTime) : 0;
    const lockRemaining = quoteLockedAt ? Math.max(0, quoteLockedAt + 180 - currentTime) : 0;
    const hasExpiry = !!effectiveExpiresAt;
    const lockActive = lockRemaining > 0;
    if (hasExpiry && !lockActive && quoteRemaining <= 0) {
      expiredHandledRef.current = true;
      onQuoteExpired?.();
    }
  }, [liveQuoteSnapshot?.expires_at, quoteMeta?.expiresAt, quoteLockedAt, completed, onQuoteExpired]);
  const handleSlippageChange = async (newSlippageConfig) => {
    if (!onSlippageChange) {
      return;
    }
    if (!checkoutSessionId) {
      onSlippageChange(newSlippageConfig);
      return;
    }
    try {
      await api.put(`/api/checkout-sessions/${checkoutSessionId}/slippage`, {
        slippage_config: newSlippageConfig
      });
      onSlippageChange(newSlippageConfig);
      if (onQuoteExpired) {
        await onQuoteExpired(true);
      }
    } catch (err) {
      console.error("Failed to update slippage", err);
      Toast.error(err.response?.data?.error || formatError(err));
    }
  };
  useBus(
    "error.REQUIRE_CROSS_SELL",
    () => {
      setState({ shake: true });
      setTimeout(() => {
        setState({ shake: false });
      }, 1e3);
    },
    []
  );
  const handleUpsell = async (from, to) => {
    await onUpsell(from, to);
    runAsync(false);
  };
  const handleQuantityChange = async (itemId, quantity) => {
    await onQuantityChange(itemId, quantity);
    runAsync(false);
  };
  const handleDownsell = async (from) => {
    await onDownsell(from);
    runAsync(false);
  };
  const handleApplyCrossSell = async () => {
    if (data) {
      try {
        setState({ loading: true });
        await onApplyCrossSell(data.id);
      } catch (err) {
        console.error(err);
      } finally {
        setState({ loading: false });
      }
    }
  };
  const handleCancelCrossSell = async () => {
    try {
      setState({ loading: true });
      await onCancelCrossSell();
    } catch (err) {
      console.error(err);
    } finally {
      setState({ loading: false });
    }
  };
  const hasSubTotal = +staking > 0 || allowPromotionCodes;
  const ProductCardList = /* @__PURE__ */ jsxs(
    Stack,
    {
      className: "cko-product-list",
      sx: {
        flex: "0 1 auto",
        overflow: "auto"
      },
      children: [
        /* @__PURE__ */ jsx(Stack, { spacing: { xs: 1, sm: 2 }, children: items.map(
          (x) => x.price?.custom_unit_amount && onChangeAmount && donationSettings ? /* @__PURE__ */ jsx(
            ProductDonation,
            {
              item: x,
              settings: donationSettings,
              onChange: onChangeAmount,
              currency: discountCurrency
            },
            `${x.price_id}-${discountCurrency.id}`
          ) : /* @__PURE__ */ jsx(
            ProductItem,
            {
              item: x,
              items,
              trialInDays,
              trialEnd,
              currency: discountCurrency,
              exchangeRate: rateInfo.exchangeRate,
              isStripePayment,
              isPriceLocked,
              isRateLoading,
              onUpsell: handleUpsell,
              onDownsell: handleDownsell,
              adjustableQuantity: x.adjustable_quantity,
              completed,
              showFeatures,
              onQuantityChange: handleQuantityChange,
              discounts: sessionDiscounts,
              calculatedDiscountAmount: calculatedDiscountAmount || (isStripePayment ? discountAmount.toString() : null),
              children: x.cross_sell && /* @__PURE__ */ jsxs(
                Stack,
                {
                  direction: "row",
                  sx: {
                    alignItems: "center",
                    justifyContent: "space-between",
                    width: 1
                  },
                  children: [
                    /* @__PURE__ */ jsx(Typography, {}),
                    /* @__PURE__ */ jsx(
                      LoadingButton,
                      {
                        size: "small",
                        loadingPosition: "end",
                        endIcon: null,
                        color: "error",
                        variant: "text",
                        loading: state.loading,
                        onClick: handleCancelCrossSell,
                        children: t("payment.checkout.cross_sell.remove")
                      }
                    )
                  ]
                }
              )
            },
            `${x.price_id}-${discountCurrency.id}`
          )
        ) }),
        data && items.some((x) => x.price_id === data.id) === false && /* @__PURE__ */ jsx(Grow, { in: true, children: /* @__PURE__ */ jsx(Stack, { sx: { mt: 1 }, children: /* @__PURE__ */ jsx(
          ProductItem,
          {
            item: { quantity: 1, price: data, price_id: data.id, cross_sell: true },
            items,
            trialInDays,
            currency: discountCurrency,
            trialEnd,
            exchangeRate: rateInfo.exchangeRate,
            isStripePayment,
            isPriceLocked,
            isRateLoading,
            onUpsell: noop,
            onDownsell: noop,
            children: /* @__PURE__ */ jsxs(
              Stack,
              {
                direction: "row",
                sx: {
                  alignItems: "center",
                  justifyContent: "space-between",
                  width: 1
                },
                children: [
                  /* @__PURE__ */ jsx(Typography, { children: crossSellBehavior === "required" && /* @__PURE__ */ jsx(Status, { label: t("payment.checkout.required"), color: "info", variant: "outlined", sx: { mr: 1 } }) }),
                  /* @__PURE__ */ jsx(
                    LoadingButton,
                    {
                      size: "small",
                      loadingPosition: "end",
                      endIcon: null,
                      color: crossSellBehavior === "required" ? "info" : "info",
                      variant: crossSellBehavior === "required" ? "text" : "text",
                      loading: state.loading,
                      onClick: handleApplyCrossSell,
                      children: t("payment.checkout.cross_sell.add")
                    }
                  )
                ]
              }
            )
          }
        ) }) })
      ]
    }
  );
  if (!discountCurrency || !items?.length) {
    return null;
  }
  return /* @__PURE__ */ jsx(Fade, { in: true, children: /* @__PURE__ */ jsxs(Stack, { className: "cko-product", direction: "column", ...rest, children: [
    /* @__PURE__ */ jsxs(
      Box,
      {
        sx: {
          display: "flex",
          alignItems: "center",
          mb: 2.5
        },
        children: [
          /* @__PURE__ */ jsx(
            Typography,
            {
              title: t("payment.checkout.orderSummary"),
              sx: {
                color: "text.primary",
                fontSize: { xs: "18px", md: "24px" },
                fontWeight: "700",
                lineHeight: "32px"
              },
              children: action || t("payment.checkout.orderSummary")
            }
          ),
          !settings.livemode && /* @__PURE__ */ jsx(Livemode, {})
        ]
      }
    ),
    effectiveHasDynamicPricing && rateUnavailable && /* @__PURE__ */ jsx(DynamicPricingUnavailable, { sx: { mb: 2 }, onRetry: onRefreshRate }),
    isMobile && !donationSettings ? /* @__PURE__ */ jsxs(Fragment, { children: [
      /* @__PURE__ */ jsxs(
        Stack,
        {
          onClick: () => setState({ expanded: !state.expanded }),
          sx: {
            justifyContent: "space-between",
            flexDirection: "row",
            alignItems: "center",
            mb: 1.5
          },
          children: [
            /* @__PURE__ */ jsx(Typography, { children: t("payment.checkout.productListTotal", { total: items.length }) }),
            /* @__PURE__ */ jsx(ExpandMore, { expand: state.expanded, "aria-expanded": state.expanded, "aria-label": "show more", children: /* @__PURE__ */ jsx(ExpandMoreIcon, {}) })
          ]
        }
      ),
      /* @__PURE__ */ jsx(Collapse, { in: state.expanded || !isMobile, timeout: "auto", unmountOnExit: true, children: ProductCardList })
    ] }) : ProductCardList,
    /* @__PURE__ */ jsx(Divider, { sx: { mt: 2.5, mb: 2.5 } }),
    +staking > 0 && /* @__PURE__ */ jsxs(Stack, { spacing: 1, children: [
      /* @__PURE__ */ jsxs(Stack, { direction: "row", spacing: 1, sx: { justifyContent: "space-between", alignItems: "center" }, children: [
        /* @__PURE__ */ jsxs(Stack, { direction: "row", spacing: 0.5, sx: { alignItems: "center" }, children: [
          /* @__PURE__ */ jsx(Typography, { sx: { color: "text.secondary" }, children: t("payment.checkout.paymentRequired") }),
          /* @__PURE__ */ jsx(Tooltip, { title: t("payment.checkout.stakingConfirm"), placement: "top", sx: { maxWidth: "150px" }, children: /* @__PURE__ */ jsx(HelpOutline, { fontSize: "small", sx: { color: "text.lighter" } }) })
        ] }),
        /* @__PURE__ */ jsx(Typography, { children: headlineAmountDisplay })
      ] }),
      /* @__PURE__ */ jsxs(Stack, { direction: "row", spacing: 1, sx: { justifyContent: "space-between", alignItems: "center" }, children: [
        /* @__PURE__ */ jsxs(Stack, { direction: "row", spacing: 0.5, sx: { alignItems: "center" }, children: [
          /* @__PURE__ */ jsx(Typography, { sx: { color: "text.secondary" }, children: t("payment.checkout.staking.title") }),
          /* @__PURE__ */ jsx(Tooltip, { title: t("payment.checkout.staking.tooltip"), placement: "top", sx: { maxWidth: "150px" }, children: /* @__PURE__ */ jsx(HelpOutline, { fontSize: "small", sx: { color: "text.lighter" } }) })
        ] }),
        /* @__PURE__ */ jsxs(Typography, { children: [
          formatAmount(staking, discountCurrency.decimal),
          " ",
          discountCurrency.symbol
        ] })
      ] })
    ] }),
    (allowPromotionCodes || hasDiscounts) && /* @__PURE__ */ jsxs(
      Stack,
      {
        direction: "row",
        spacing: 1,
        sx: {
          justifyContent: "space-between",
          alignItems: "center",
          ...+staking > 0 && {
            borderTop: "1px solid",
            borderColor: "divider",
            pt: 1,
            mt: 1
          }
        },
        children: [
          /* @__PURE__ */ jsx(Typography, { className: "base-label", children: t("common.subtotal") }),
          /* @__PURE__ */ jsxs(Typography, { children: [
            subtotalDisplay,
            " ",
            discountCurrency.symbol
          ] })
        ]
      }
    ),
    /* @__PURE__ */ jsx(
      PromotionSection,
      {
        checkoutSessionId: checkoutSession?.id || checkoutSessionId,
        currency: discountCurrency,
        currencyId: currency.id,
        discounts: sessionDiscounts,
        allowPromotionCodes,
        completed,
        disabled: paymentState.paying || paymentState.stripePaying,
        onPromotionUpdate: handlePromotionUpdate,
        onRemovePromotion: handleRemovePromotion,
        calculatedDiscountAmount: calculatedDiscountAmount || (isStripePayment ? discountAmount.toString() : null),
        isRateLoading
      }
    ),
    hasSubTotal && /* @__PURE__ */ jsx(Divider, { sx: { my: 1 } }),
    /* @__PURE__ */ jsx(
      TotalSection,
      {
        totalAmountText,
        totalUsdDisplay,
        currency: discountCurrency,
        hasDynamicPricing,
        rateDisplay,
        rateInfo,
        quoteDetailRows,
        currentSlippagePercent,
        slippageConfig,
        isPriceLocked,
        isSubscription,
        completed,
        onSlippageChange: onSlippageChange ? handleSlippageChange : void 0,
        isStripePayment,
        isRateLoading,
        thenInfo: headlines.thenValue && headlines.showThen ? headlines.thenValue : void 0
      }
    )
  ] }) });
}
