/* eslint-disable @typescript-eslint/indent */
import { useLocaleContext } from '@arcblock/ux/lib/Locale/context';
import type { PriceRecurring, TLineItemExpanded, TPaymentCurrency } from '@blocklet/payment-types';
import { Box, Stack, Typography, IconButton, TextField, Alert, Chip } from '@mui/material';
import { Add, Remove, LocalOffer } from '@mui/icons-material';

import React, { useEffect, useMemo, useState } from 'react';
import { useRequest } from 'ahooks';
import { BN, fromTokenToUnit, fromUnitToToken } from '@ocap/util';
import LoadingAmount from '../components/loading-amount';
import Status from '../components/status';
import Switch from '../components/switch-button';
import {
  findCurrency,
  formatLineItemPricing,
  formatNumber,
  formatPrice,
  formatQuantityInventory,
  formatRecurring,
  formatUpsellSaving,
  formatAmount,
  formatCreditForCheckout,
  formatCreditAmount,
  formatBNStr,
  getUsdAmountFromBaseAmount,
  formatUsdAmount,
  formatDynamicPrice,
} from '../libs/util';
import ProductCard from './product-card';
import dayjs from '../libs/dayjs';
import { usePaymentContext } from '../contexts/payment';

interface DiscountInfo {
  promotion_code?: string;
  coupon?: string;
  discount_amount?: string;
  promotion_code_details?: {
    code?: string;
  };
  coupon_details?: {
    percent_off?: number;
    amount_off?: string;
    currency_id?: string;
    currency_options?: Record<string, { amount_off?: string }>;
  };
  verification_data?: {
    code?: string;
  };
}

type Props = {
  item: TLineItemExpanded;
  items: TLineItemExpanded[];
  trialInDays: number;
  trialEnd?: number;
  currency: TPaymentCurrency;
  onUpsell: Function;
  onDownsell: Function;
  mode?: 'normal' | 'cross-sell';
  children?: React.ReactNode;
  // 数量调整相关
  adjustableQuantity?: {
    enabled: boolean;
    minimum?: number;
    maximum?: number;
  };
  onQuantityChange?: (itemId: string, quantity: number) => void;
  completed?: boolean;
  showFeatures?: boolean;
  exchangeRate?: string | null;
  isStripePayment?: boolean;
  isPriceLocked?: boolean;
  isRateLoading?: boolean;
  // Discount display props
  discounts?: DiscountInfo[];
  calculatedDiscountAmount?: string | null;
};

const getRecommendedQuantityFromUrl = (priceId: string): number | undefined => {
  try {
    const urlParams = new URLSearchParams(window.location.search);
    const recommendedQuantity = urlParams.get(`qty_${priceId}`) || urlParams.get('qty');
    return recommendedQuantity ? Math.max(1, parseInt(recommendedQuantity, 10)) : undefined;
  } catch {
    return undefined;
  }
};

const getUserQuantityPreference = (userDid: string, priceId: string): number | undefined => {
  try {
    const key = `quantity_preference_${userDid}_${priceId}`;
    const stored = localStorage.getItem(key);
    return stored ? Math.max(1, parseInt(stored, 10)) : undefined;
  } catch {
    return undefined;
  }
};

const saveUserQuantityPreference = (userDid: string, priceId: string, quantity: number): void => {
  try {
    const key = `quantity_preference_${userDid}_${priceId}`;
    localStorage.setItem(key, quantity.toString());
  } catch {
    // Silently fail if localStorage is not available
  }
};

export default function ProductItem({
  item,
  items,
  trialInDays,
  trialEnd = 0,
  currency,
  mode = 'normal',
  children = null,
  onUpsell,
  onDownsell,
  completed = false,
  adjustableQuantity = { enabled: false },
  onQuantityChange = () => {},
  showFeatures = false,
  exchangeRate = null,
  isStripePayment = false,
  isPriceLocked = false,
  isRateLoading = false,
  discounts = [],
  calculatedDiscountAmount = null,
}: Props) {
  const { t, locale } = useLocaleContext();
  const { settings, setPayable, session, api } = usePaymentContext();
  const pricingSource = item.upsell_price || item.price;
  const isDynamicPricing = (pricingSource as any)?.pricing_type === 'dynamic';
  const pricing = formatLineItemPricing(item, currency, { trialEnd, trialInDays, exchangeRate }, locale);
  const saving = formatUpsellSaving(items, currency);
  const metered = item.price?.recurring?.usage_type === 'metered' ? t('common.metered') : '';
  const canUpsell = mode === 'normal' && items.length === 1;
  const isTrial = trialInDays > 0 || trialEnd > dayjs().unix();

  // Check if this is a credit product - be more lenient in detection
  const isCreditProduct = item.price.product?.type === 'credit' && item.price.metadata?.credit_config;
  const creditAmount =
    isCreditProduct && item.price.metadata?.credit_config?.credit_amount
      ? Number(item.price.metadata.credit_config.credit_amount)
      : 0;
  const creditCurrency =
    isCreditProduct && item.price.metadata?.credit_config?.currency_id
      ? findCurrency(settings.paymentMethods, item.price.metadata.credit_config.currency_id)
      : null;
  const validDuration = item.price.metadata?.credit_config?.valid_duration_value;
  const validDurationUnit = item.price.metadata?.credit_config?.valid_duration_unit || 'days';
  const scheduleConfig = item.price.metadata?.credit_config?.schedule;
  const hasSchedule =
    scheduleConfig?.enabled && scheduleConfig?.delivery_mode && scheduleConfig.delivery_mode !== 'invoice';

  const userDid = session?.user?.did;

  const { data: pendingAmount } = useRequest(
    async () => {
      if (!isCreditProduct || !userDid) return null;
      try {
        const { data } = await api.get('/api/meter-events/pending-amount', {
          params: {
            customer_id: userDid,
            currency_id: creditCurrency?.id,
          },
        });
        return data?.[creditCurrency?.id || ''];
      } catch (error) {
        console.warn('Failed to fetch pending amount:', error);
        return null;
      }
    },
    {
      refreshDeps: [isCreditProduct, userDid, creditCurrency?.id],
    }
  );

  const canAdjustQuantity = adjustableQuantity.enabled && mode === 'normal';

  const minQuantity = Math.max(adjustableQuantity.minimum || 1, 1);
  const quantityAvailable = Math.min(
    item.price?.quantity_limit_per_checkout ?? Infinity,
    item.price?.quantity_available ?? Infinity
  );
  const maxQuantity = quantityAvailable
    ? Math.min(adjustableQuantity.maximum || Infinity, quantityAvailable)
    : adjustableQuantity.maximum || Infinity;

  const getMinQuantityForPending = useMemo(() => {
    if (!isCreditProduct || !pendingAmount) return null;
    const pendingAmountBN = new BN(pendingAmount || '0');
    if (!pendingAmountBN.gt(new BN(0))) return null;
    // Check if creditAmount is valid (should be > 0 for non-schedule mode)
    if (!creditAmount || creditAmount <= 0) return null;
    const creditAmountBN = fromTokenToUnit(creditAmount, creditCurrency?.decimal || 2);
    // Check if creditAmountBN is zero to avoid division by zero error
    if (!creditAmountBN || creditAmountBN.isZero()) return null;
    return Math.ceil(pendingAmountBN.mul(new BN(100)).div(creditAmountBN).toNumber() / 100);
  }, [isCreditProduct, pendingAmount, creditAmount, creditCurrency?.decimal]);

  const initialQuantity = useMemo(() => {
    const urlQuantity = getRecommendedQuantityFromUrl(item.price.id);
    if (urlQuantity && urlQuantity > 0) {
      if (canAdjustQuantity && getMinQuantityForPending) {
        return Math.max(urlQuantity, getMinQuantityForPending, minQuantity);
      }
      return urlQuantity;
    }

    if (userDid) {
      const preferredQuantity = getUserQuantityPreference(userDid, item.price.id);
      if (preferredQuantity && preferredQuantity > 0) {
        if (canAdjustQuantity && getMinQuantityForPending) {
          return Math.max(preferredQuantity, getMinQuantityForPending, minQuantity);
        }
        return preferredQuantity;
      }
    }

    let baseQuantity = item.quantity;

    if (canAdjustQuantity && getMinQuantityForPending) {
      baseQuantity = Math.max(baseQuantity, getMinQuantityForPending, minQuantity);
    }

    return baseQuantity;
  }, [item.quantity, item.price.id, userDid, getMinQuantityForPending, canAdjustQuantity, minQuantity]);

  const [localQuantity, setLocalQuantity] = useState<number | undefined>(initialQuantity);
  const localQuantityNum = localQuantity || 0;

  useEffect(() => {
    if (initialQuantity && initialQuantity > 0) {
      if (initialQuantity !== localQuantity) {
        setLocalQuantity(initialQuantity);
      }
      if (initialQuantity !== item.quantity) {
        onQuantityChange(item.price_id, initialQuantity);
      }

      if (isCreditProduct && pendingAmount && getMinQuantityForPending) {
        setPayable(initialQuantity >= getMinQuantityForPending);
      } else {
        setPayable(true);
      }
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [initialQuantity, isCreditProduct, pendingAmount, getMinQuantityForPending]);

  const handleQuantityChange = (newQuantity: number) => {
    if (!newQuantity) {
      setLocalQuantity(undefined);
      setPayable(false);
      return;
    }

    if (newQuantity >= minQuantity && newQuantity <= maxQuantity) {
      if (formatQuantityInventory(item.price, newQuantity, locale)) {
        return;
      }

      if (isCreditProduct && pendingAmount && getMinQuantityForPending) {
        if (newQuantity < getMinQuantityForPending) {
          setPayable(false);
          setLocalQuantity(newQuantity);
          onQuantityChange(item.price_id, newQuantity);
          return;
        }
      }

      setPayable(true);
      setLocalQuantity(newQuantity);
      onQuantityChange(item.price_id, newQuantity);

      if (userDid && newQuantity > 0) {
        saveUserQuantityPreference(userDid, item.price?.id, newQuantity);
      }
    }
  };

  const handleQuantityIncrease = () => {
    if (localQuantityNum < maxQuantity) {
      handleQuantityChange(localQuantityNum + 1);
    }
  };

  const handleQuantityDecrease = () => {
    if (localQuantityNum > minQuantity) {
      handleQuantityChange(localQuantityNum - 1);
    }
  };

  const handleQuantityInputChange = (event: React.ChangeEvent<HTMLInputElement>) => {
    const value = parseInt(event.target.value || '0', 10);
    if (!Number.isNaN(value)) {
      handleQuantityChange(value);
    }
  };

  // Credit 信息格式化
  const formatCreditInfo = () => {
    if (!isCreditProduct) return null;

    const totalCreditStr = formatNumber(creditAmount * (localQuantity || 0));
    const currencySymbol = creditCurrency?.symbol || 'Credits';
    const formattedTotalCredit = formatCreditForCheckout(totalCreditStr, currencySymbol, locale);

    const hasPendingAmount = pendingAmount && new BN(pendingAmount || '0').gt(new BN(0));
    const isRecurring = item.price?.type === 'recurring';
    const hasExpiry = validDuration && validDuration > 0;

    const buildBaseParams = () => ({
      amount: formattedTotalCredit,
      ...(hasExpiry && {
        duration: validDuration,
        unit: t(`common.${validDurationUnit}`),
      }),
      ...(isRecurring && {
        period: formatRecurring(item.price?.recurring!, true, 'per', locale),
      }),
    });

    const buildPendingParams = (pendingBN: BN, availableAmount?: string) => ({
      amount: formatCreditForCheckout(
        formatBNStr(pendingBN.toString(), creditCurrency?.decimal || 2),
        currencySymbol,
        locale
      ),
      totalAmount: formattedTotalCredit,
      ...(availableAmount && {
        availableAmount: formatCreditForCheckout(
          formatBNStr(availableAmount, creditCurrency?.decimal || 2),
          currencySymbol,
          locale
        ),
      }),
      ...(hasExpiry && {
        duration: validDuration,
        unit: t(`common.${validDurationUnit}`),
      }),
      ...(isRecurring && {
        period: formatRecurring(item.price?.recurring!, true, 'per', locale),
      }),
    });

    const getLocaleKey = (category: 'normal' | 'pending', type: string) => {
      const suffix = hasExpiry ? 'WithExpiry' : '';
      return `payment.checkout.credit.${category}.${type}${suffix}`;
    };

    if (!hasPendingAmount) {
      const type = isRecurring ? 'recurring' : 'oneTime';
      return t(getLocaleKey('normal', type), buildBaseParams());
    }

    const pendingAmountBN = new BN(pendingAmount || '0');
    const creditAmountBN = fromTokenToUnit(creditAmount, creditCurrency?.decimal || 2);
    const minQuantityNeeded = getMinQuantityForPending || 0;
    const currentPurchaseCreditBN = creditAmountBN.mul(new BN(localQuantity || 0));
    const actualAvailable = currentPurchaseCreditBN.sub(pendingAmountBN).toString();

    if (!new BN(actualAvailable).gt(new BN(0))) {
      return t('payment.checkout.credit.pending.notEnough', {
        amount: formatCreditForCheckout(
          formatBNStr(pendingAmountBN.toString(), creditCurrency?.decimal || 2),
          currencySymbol,
          locale
        ),
        quantity: formatNumber(minQuantityNeeded),
      });
    }

    const type = isRecurring ? 'recurringEnough' : 'oneTimeEnough';
    return t(getLocaleKey('pending', type), buildPendingParams(pendingAmountBN, actualAvailable));
  };

  const quantityForUsd = Number.isFinite(localQuantity) ? Number(localQuantity) : item.quantity || 0;

  // For dynamic pricing, calculate token display from live exchange rate
  // Final Freeze: Only use live rate (prop) for preview, quoted_amount for locked quotes
  // Also supports non-dynamic pricing with exchange rate (e.g., cross-sell products)
  const dynamicTokenDisplay = useMemo(() => {
    if (isStripePayment || !currency) {
      return null;
    }

    // Get USD amount: prefer base_amount (dynamic pricing), fallback to unit_amount (fixed pricing)
    const baseAmount = (pricingSource as any)?.base_amount;
    const unitAmount = pricingSource?.unit_amount;

    // For dynamic pricing products
    if (isDynamicPricing && baseAmount !== undefined && baseAmount !== null) {
      // Only use quoted_amount when price is locked (after submit)
      if (isPriceLocked) {
        const quotedAmount = (item as any)?.quoted_amount;
        if (quotedAmount) {
          const totalBN = new BN(quotedAmount);
          const tokenValue = fromUnitToToken(totalBN, currency.decimal);
          return `${formatDynamicPrice(tokenValue, true, 6)} ${currency.symbol}`;
        }
      }

      if (!exchangeRate) {
        return null;
      }
      const rate = Number(exchangeRate);
      if (rate <= 0 || Number.isNaN(rate)) {
        return null;
      }
      // base_amount is stored in dollar format (e.g., "1.00" = $1.00), NOT cents
      const usdAmount = Number(baseAmount);
      const tokenAmount = usdAmount / rate;
      const totalTokens = tokenAmount * (quantityForUsd || 1);
      return `${formatDynamicPrice(totalTokens, true, 6)} ${currency.symbol}`;
    }

    // For non-dynamic pricing products (e.g., cross-sell): convert USD to current currency using rate
    // This allows showing "10 PLAY3" instead of "$1.00" when paying with crypto
    if (!isDynamicPricing && exchangeRate && unitAmount) {
      const rate = Number(exchangeRate);
      if (rate <= 0 || Number.isNaN(rate)) {
        return null;
      }
      // unit_amount is in cents, convert to dollars first
      const usdAmount = Number(unitAmount) / 100;
      const tokenAmount = usdAmount / rate;
      const totalTokens = tokenAmount * (quantityForUsd || 1);
      return `${formatDynamicPrice(totalTokens, true, 6)} ${currency.symbol}`;
    }

    return null;
  }, [isStripePayment, isDynamicPricing, currency, pricingSource, item, exchangeRate, quantityForUsd, isPriceLocked]);

  // Format credit schedule info for display
  const formatScheduleInfo = () => {
    if (!hasSchedule || !scheduleConfig) return null;

    const totalCredit = creditAmount * (localQuantity || 0);
    const currencySymbol = creditCurrency?.symbol || 'Credits';
    const intervalUnit = scheduleConfig.interval_unit;
    const intervalValue = scheduleConfig.interval_value;

    // Calculate amount per grant
    let amountPerGrant: number;
    if (scheduleConfig.amount_per_grant) {
      amountPerGrant = Number(scheduleConfig.amount_per_grant) * (localQuantity || 1);
    } else {
      // Divide total by period intervals
      const billingIntervalUnit = item.price.recurring?.interval || 'month';
      const billingIntervalCount = item.price.recurring?.interval_count || 1;

      // Calculate how many schedule intervals fit in billing period
      const unitToHours: Record<string, number> = {
        hour: 1,
        day: 24,
        week: 168,
        month: 720, // ~30 days
      };
      const billingHours = unitToHours[billingIntervalUnit] * billingIntervalCount;
      const scheduleHours = unitToHours[intervalUnit] * intervalValue;
      const grantsPerPeriod = Math.floor(billingHours / scheduleHours);
      amountPerGrant = grantsPerPeriod > 0 ? totalCredit / grantsPerPeriod : totalCredit;
    }
    const formattedAmount = formatCreditAmount(formatNumber(amountPerGrant), currencySymbol);

    const intervalDisplay =
      intervalValue === 1
        ? t(`common.${intervalUnit}`)
        : ` ${intervalValue} ${t(`common.${intervalUnit}s` as 'common.hours' | 'common.days' | 'common.weeks' | 'common.months')} `;

    const expireWithNext = scheduleConfig.expire_with_next_grant;

    if (expireWithNext) {
      return t('payment.checkout.credit.schedule.withRefresh', {
        amount: formattedAmount,
        interval: intervalDisplay,
      });
    }

    return t('payment.checkout.credit.schedule.periodic', {
      amount: formattedAmount,
      interval: intervalDisplay,
    });
  };

  const primaryText = useMemo(() => {
    const price = item.upsell_price || item.price || {};
    const isRecurring = price?.type === 'recurring' && price?.recurring;

    // For trial scenarios, always use the formatted trial message from pricing.primary
    // (e.g., "Free 7-day trial") instead of the calculated token amount
    if (isTrial) {
      return pricing.primary;
    }

    // Determine display amount based on payment type and available data
    let displayAmount: string;

    // If we have dynamicTokenDisplay (dynamic pricing OR cross-sell with exchange rate), use it
    if (!isStripePayment && dynamicTokenDisplay) {
      displayAmount = dynamicTokenDisplay;
    } else if (isDynamicPricing && !isStripePayment) {
      // Dynamic pricing but no rate available - show USD fallback
      const baseAmount = (pricingSource as any)?.base_amount;
      if (baseAmount !== undefined && baseAmount !== null) {
        const usdValue = Number(baseAmount);
        displayAmount = `≈ $${usdValue.toFixed(2)}`;
      } else {
        displayAmount = pricing.primary;
      }
    } else {
      // Stripe payment or no special handling needed
      displayAmount = pricing.primary;
    }

    if (isRecurring && price?.recurring?.usage_type !== 'metered') {
      return `${displayAmount} ${price.recurring ? formatRecurring(price.recurring, false, 'slash', locale) : ''}`;
    }
    return displayAmount;
  }, [isTrial, pricing, item, locale, dynamicTokenDisplay, isDynamicPricing, pricingSource, isStripePayment]);

  const usdReference = useMemo(() => {
    // Stripe payments don't need USD reference - base_amount is already USD
    if (!currency || !isDynamicPricing || isStripePayment) {
      return null;
    }
    const baseAmount = (pricingSource as any)?.base_amount;
    const hasBaseAmount = baseAmount !== undefined && baseAmount !== null;
    if (hasBaseAmount) {
      return getUsdAmountFromBaseAmount(baseAmount, quantityForUsd);
    }
    return null;
  }, [currency, pricingSource, quantityForUsd, isDynamicPricing, isStripePayment]);
  const usdReferenceDisplay = useMemo(() => formatUsdAmount(usdReference, locale), [usdReference, locale]);

  // Calculate upsell price display with exchange rate conversion
  // Shows "X PLAY3 每月" instead of "$1.00 每月" when paying with crypto
  // For Stripe, shows "1 USD 每月" instead of "$1.00 每月"
  const upsellTokenDisplay = useMemo(() => {
    const upsellPrice = item.price?.upsell?.upsells_to;
    if (!upsellPrice) {
      return null;
    }

    // For Stripe payment: format as "1 USD 每月" instead of "$1.00 每月"
    if (isStripePayment && currency) {
      const baseAmount = (upsellPrice as any)?.base_amount;
      const unitAmount = upsellPrice?.unit_amount;

      let usdAmount: number;
      if (baseAmount !== undefined && baseAmount !== null) {
        usdAmount = Number(baseAmount);
      } else if (unitAmount) {
        usdAmount = Number(unitAmount) / 100;
      } else {
        return null;
      }

      const recurring = upsellPrice?.recurring
        ? ` ${formatRecurring(upsellPrice.recurring, false, 'slash', locale)}`
        : '';
      return `${usdAmount} ${currency.symbol}${recurring}`;
    }

    // For crypto payment: need exchange rate
    if (!currency || !exchangeRate) {
      return null;
    }

    const rate = Number(exchangeRate);
    if (rate <= 0 || Number.isNaN(rate)) {
      return null;
    }

    // Get USD amount: prefer base_amount (dynamic pricing), fallback to unit_amount (fixed pricing)
    const baseAmount = (upsellPrice as any)?.base_amount;
    const unitAmount = upsellPrice?.unit_amount;

    let usdAmount: number;
    if (baseAmount !== undefined && baseAmount !== null) {
      // base_amount is in dollar format (e.g., "1.00" = $1.00)
      usdAmount = Number(baseAmount);
    } else if (unitAmount) {
      // unit_amount is in cents
      usdAmount = Number(unitAmount) / 100;
    } else {
      return null;
    }

    const tokenAmount = usdAmount / rate;
    const recurring = upsellPrice?.recurring
      ? ` ${formatRecurring(upsellPrice.recurring, false, 'slash', locale)}`
      : '';
    return `${formatDynamicPrice(tokenAmount, true, 6)} ${currency.symbol}${recurring}`;
  }, [isStripePayment, currency, exchangeRate, item.price?.upsell?.upsells_to, locale]);

  // Calculate downsell price display with exchange rate conversion
  // Shows "X ABT 每天" instead of "$0.50 每天" when paying with crypto
  const downsellTokenDisplay = useMemo(() => {
    // Only show when upsell is active (item.upsell_price_id exists)
    if (!item.upsell_price_id || !item.price) {
      return null;
    }

    const originalPrice = item.price;

    // For Stripe payment: format as "0.5 USD 每天" instead of "$0.50 每天"
    if (isStripePayment && currency) {
      const baseAmount = (originalPrice as any)?.base_amount;
      const unitAmount = originalPrice?.unit_amount;

      let usdAmount: number;
      if (baseAmount !== undefined && baseAmount !== null) {
        usdAmount = Number(baseAmount);
      } else if (unitAmount) {
        usdAmount = Number(unitAmount) / 100;
      } else {
        return null;
      }

      const recurring = originalPrice?.recurring
        ? ` ${formatRecurring(originalPrice.recurring, false, 'slash', locale)}`
        : '';
      return `${usdAmount} ${currency.symbol}${recurring}`;
    }

    // For crypto payment: need exchange rate
    if (!currency || !exchangeRate) {
      return null;
    }

    const rate = Number(exchangeRate);
    if (rate <= 0 || Number.isNaN(rate)) {
      return null;
    }

    // Get USD amount: prefer base_amount (dynamic pricing), fallback to unit_amount (fixed pricing)
    const baseAmount = (originalPrice as any)?.base_amount;
    const unitAmount = originalPrice?.unit_amount;

    let usdAmount: number;
    if (baseAmount !== undefined && baseAmount !== null) {
      usdAmount = Number(baseAmount);
    } else if (unitAmount) {
      usdAmount = Number(unitAmount) / 100;
    } else {
      return null;
    }

    const tokenAmount = usdAmount / rate;
    const recurring = originalPrice?.recurring
      ? ` ${formatRecurring(originalPrice.recurring, false, 'slash', locale)}`
      : '';
    return `${formatDynamicPrice(tokenAmount, true, 6)} ${currency.symbol}${recurring}`;
  }, [isStripePayment, currency, exchangeRate, item.price, item.upsell_price_id, locale]);

  // Calculate frontend-displayed discount amount for this item
  // For dynamic pricing: use coupon info + exchange rate to calculate
  // For Stripe: calculate from USD amounts
  // For single-item scenarios: use calculatedDiscountAmount directly
  const displayItemDiscountAmount = useMemo(() => {
    // Skip discount display when no payment is made:
    // 1. During trial for recurring items - trial period has no charge
    // 2. Metered pricing - initial amount is 0 (charged based on actual usage)
    if ((isTrial && item.price?.type === 'recurring') || item.price?.recurring?.usage_type === 'metered') {
      return null;
    }

    // Skip if no discounts
    if (!discounts?.length) {
      return null;
    }

    const couponDetails = discounts[0]?.coupon_details;

    // For Stripe payment: calculate discount from USD amounts (in cents)
    if (isStripePayment && couponDetails) {
      // Check if this item is discountable
      if (!(item as any).discountable) {
        return null;
      }

      // Get item's USD amount in cents
      const isDynamic = (pricingSource as any)?.pricing_type === 'dynamic';
      const baseAmount = (pricingSource as any)?.base_amount;
      const unitAmount = pricingSource?.unit_amount;

      let amountCents: number;
      if (isDynamic && baseAmount !== undefined && baseAmount !== null) {
        // base_amount is in dollars, convert to cents
        amountCents = Number(baseAmount) * 100;
      } else if (unitAmount) {
        // unit_amount is in cents
        amountCents = Number(unitAmount);
      } else {
        return null;
      }

      const quantity = localQuantity || item.quantity || 1;
      const itemSubtotalCents = amountCents * quantity;

      // For percent_off: itemAmount * percent_off / 100
      if (couponDetails.percent_off && couponDetails.percent_off > 0) {
        const discountCents = Math.round((itemSubtotalCents * couponDetails.percent_off) / 100);
        return discountCents.toString();
      }

      // For amount_off with single item: use the passed calculatedDiscountAmount
      if (couponDetails.amount_off && items.length === 1 && calculatedDiscountAmount) {
        return calculatedDiscountAmount;
      }

      return null;
    }

    // For dynamic pricing with live rate, calculate discount from scratch
    if (isDynamicPricing && exchangeRate && couponDetails) {
      const rateNum = Number(exchangeRate);
      if (rateNum <= 0) {
        return null;
      }

      // Check if this item is discountable
      if (!(item as any).discountable) {
        return null;
      }

      // Get item's base amount
      const baseAmount = (pricingSource as any)?.base_amount;
      if (!baseAmount) {
        return null;
      }

      const quantity = localQuantity || item.quantity || 1;
      const itemTokenAmount = (Number(baseAmount) * quantity) / rateNum;

      // For percent_off: itemAmount * percent_off / 100
      if (couponDetails.percent_off && couponDetails.percent_off > 0) {
        const discountAmount = (itemTokenAmount * couponDetails.percent_off) / 100;
        const discountAmountUnit = fromTokenToUnit(
          discountAmount.toFixed(currency.decimal || 8),
          currency.decimal || 8
        );
        return discountAmountUnit.toString();
      }

      // For amount_off with single item: use the passed calculatedDiscountAmount
      if (couponDetails.amount_off && items.length === 1 && calculatedDiscountAmount) {
        return calculatedDiscountAmount;
      }
    }

    // Fallback for single item: use passed calculatedDiscountAmount
    if (items.length === 1 && calculatedDiscountAmount) {
      return calculatedDiscountAmount;
    }

    return null;
  }, [
    isTrial,
    discounts,
    isStripePayment,
    isDynamicPricing,
    exchangeRate,
    item,
    pricingSource,
    localQuantity,
    currency.decimal,
    items.length,
    calculatedDiscountAmount,
  ]);

  // Get discount code for display
  const discountCodeDisplay = useMemo(() => {
    if (!discounts?.length) return null;
    const discount = discounts[0];
    return discount.promotion_code_details?.code || discount.verification_data?.code || 'DISCOUNT';
  }, [discounts]);

  const quantityInventoryError = formatQuantityInventory(item.price, localQuantityNum, locale);
  const features = item.price?.product?.features || [];

  return (
    <Stack
      direction="column"
      spacing={1}
      className="product-item"
      sx={{
        alignItems: 'flex-start',
        width: '100%',
      }}>
      <Stack
        direction="column"
        className="product-item-content"
        sx={{
          alignItems: 'flex-start',
          width: '100%',
        }}>
        <Stack
          direction="row"
          spacing={0.5}
          sx={{
            alignItems: 'center',
            flexWrap: 'wrap',
            justifyContent: 'space-between',
            width: '100%',
          }}>
          <ProductCard
            logo={item.price?.product?.images[0]}
            name={item.price?.product?.name}
            // description={showDescription ? item.price?.product?.description : undefined}
            extra={
              <Box
                sx={{
                  display: 'flex',
                  alignItems: 'center',
                }}>
                {item.price?.type === 'recurring' && item.price?.recurring
                  ? [pricing.quantity, t('common.billed', { rule: `${formatRecurring(item.upsell_price?.recurring || item.price?.recurring, true, 'per', locale)} ${metered}` })].filter(Boolean).join(', ') // prettier-ignore
                  : pricing.quantity}
              </Box>
            }
          />
          <Stack
            direction="column"
            sx={{
              alignItems: 'flex-end',
              flex: 1,
            }}>
            <LoadingAmount
              value={primaryText}
              loading={isRateLoading}
              skeletonWidth={80}
              height={20}
              sx={{ color: 'text.primary', fontWeight: 500 }}
            />
            {/* For trial scenarios, don't show USD reference or secondary pricing - they're redundant */}
            {/* No skeleton needed - USD equivalent is based on base_amount which doesn't change */}
            {isDynamicPricing && !isStripePayment && !isTrial && usdReferenceDisplay && (
              <Typography sx={{ fontSize: '0.74375rem', color: 'text.lighter' }}>≈ ${usdReferenceDisplay}</Typography>
            )}
            {pricing.secondary && !isTrial && (
              <Typography sx={{ fontSize: '0.74375rem', color: 'text.lighter' }}>{pricing.secondary}</Typography>
            )}
          </Stack>
        </Stack>

        {/* Display discount information for this item */}
        {/* Priority: use frontend-calculated displayItemDiscountAmount for dynamic pricing */}
        {/* Fallback: use backend item.discount_amounts for non-dynamic pricing */}
        {/* Hide when no payment: trial for recurring items, or metered pricing (initial amount is 0) */}
        {!((isTrial && item.price?.type === 'recurring') || item.price?.recurring?.usage_type === 'metered') &&
          (displayItemDiscountAmount || (item.discount_amounts && item.discount_amounts.length > 0)) && (
            <Stack
              direction="row"
              spacing={1}
              sx={{
                mt: 1,
                alignItems: 'center',
                opacity: isRateLoading ? 0 : 1,
                transition: 'opacity 300ms ease-in-out',
              }}>
              <Chip
                icon={<LocalOffer sx={{ fontSize: '0.8rem !important' }} />}
                label={
                  <Box sx={{ display: 'flex', alignItems: 'center', gap: 0.5 }}>
                    <Typography component="span" sx={{ fontSize: '0.75rem', fontWeight: 'medium' }}>
                      {discountCodeDisplay || 'DISCOUNT'}
                    </Typography>
                    <Typography component="span" sx={{ fontSize: '0.75rem' }}>
                      (-
                      {formatAmount(
                        displayItemDiscountAmount || item.discount_amounts?.[0]?.amount || '0',
                        currency.decimal
                      )}{' '}
                      {currency.symbol})
                    </Typography>
                  </Box>
                }
                size="small"
                variant="filled"
                sx={{
                  height: 20,
                  '& .MuiChip-icon': {
                    color: 'warning.main',
                  },
                  '& .MuiChip-label': {
                    px: 1,
                  },
                }}
              />
            </Stack>
          )}

        {showFeatures && features.length > 0 && (
          <Box
            sx={{
              display: 'flex',
              alignItems: 'center',
              justifyContent: 'flex-start',
              flexWrap: 'wrap',
              gap: 1.5,
              width: '100%',
              mt: 1.5,
            }}>
            {features.map((feature) => (
              <Box
                key={feature.name}
                sx={{
                  display: 'flex',
                  alignItems: 'center',
                  justifyContent: 'center',
                  gap: 0.5,
                  px: 1,
                  py: 0.5,
                  bgcolor: 'action.hover',
                  borderRadius: 1,
                  border: '1px solid',
                  borderColor: 'divider',
                }}>
                <Box
                  sx={{
                    bgcolor: 'success.main',
                    width: 4,
                    height: 4,
                    borderRadius: '50%',
                  }}
                />
                <Typography
                  component="span"
                  variant="caption"
                  sx={{
                    color: 'text.primary',
                    fontSize: '0.75rem',
                    fontWeight: 500,
                    textTransform: 'capitalize',
                    whiteSpace: 'nowrap',
                  }}>
                  {feature.name}
                </Typography>
              </Box>
            ))}
          </Box>
        )}
        {quantityInventoryError ? (
          <Status
            label={quantityInventoryError}
            variant="outlined"
            sx={{
              mt: 1,
              borderColor: 'chip.error.border',
              backgroundColor: 'chip.error.background',
              color: 'chip.error.text',
            }}
          />
        ) : null}

        {/* 数量调整器 */}
        {canAdjustQuantity && !completed && (
          <Box sx={{ mt: 1, p: 1 }}>
            <Stack
              direction="row"
              spacing={1}
              sx={{
                alignItems: 'center',
              }}>
              <Typography
                variant="body2"
                sx={{
                  color: 'text.secondary',
                  minWidth: 'fit-content',
                }}>
                {t('common.quantity')}:
              </Typography>
              <IconButton
                size="small"
                onClick={handleQuantityDecrease}
                disabled={localQuantityNum <= minQuantity}
                sx={{ minWidth: 32, width: 32, height: 32 }}>
                <Remove fontSize="small" />
              </IconButton>
              <TextField
                size="small"
                value={localQuantity}
                onChange={handleQuantityInputChange}
                type="number"
                slotProps={{
                  htmlInput: {
                    min: minQuantity,
                    max: maxQuantity,
                    style: { textAlign: 'center', padding: '4px', minWidth: 80 },
                  },
                }}
              />
              <IconButton
                size="small"
                onClick={handleQuantityIncrease}
                disabled={localQuantityNum >= maxQuantity}
                sx={{ minWidth: 32, width: 32, height: 32 }}>
                <Add fontSize="small" />
              </IconButton>
            </Stack>
          </Box>
        )}

        {/* Credit 信息展示 */}
        {isCreditProduct && (
          <Alert severity="info" sx={{ mt: 1, fontSize: '0.875rem' }} icon={false}>
            {hasSchedule ? (
              <Typography component="span" sx={{ fontSize: 'inherit' }}>
                {formatScheduleInfo()}
              </Typography>
            ) : (
              <Typography component="span" sx={{ fontSize: 'inherit' }}>
                {formatCreditInfo()}
              </Typography>
            )}
          </Alert>
        )}

        {children}
      </Stack>
      {canUpsell && !item.upsell_price_id && item.price?.upsell?.upsells_to && (
        <Stack
          direction="row"
          className="product-item-upsell"
          sx={{
            alignItems: 'center',
            justifyContent: 'space-between',
            width: '100%',
          }}>
          <Typography
            component="label"
            htmlFor="upsell-switch"
            sx={{
              fontSize: 12,
              cursor: 'pointer',
              color: 'text.secondary',
            }}>
            <Switch
              id="upsell-switch"
              sx={{ mr: 1 }}
              variant="success"
              checked={false}
              onChange={() => onUpsell(item.price_id, item.price?.upsell?.upsells_to_id)}
            />
            {t('payment.checkout.upsell.save', {
              recurring: formatRecurring(
                item.price?.upsell?.upsells_to?.recurring as PriceRecurring,
                true,
                'per',
                locale
              ),
            })}
            <Status
              label={t('payment.checkout.upsell.off', { saving })}
              variant="outlined"
              sx={{
                ml: 1,
                borderColor: 'chip.warning.border',
                backgroundColor: 'chip.warning.background',
                color: 'chip.warning.text',
              }}
            />
          </Typography>
          <Typography component="span" sx={{ fontSize: 12 }}>
            {upsellTokenDisplay ||
              formatPrice(item.price?.upsell?.upsells_to, currency, item.price?.product?.unit_label, 1, true, locale)}
          </Typography>
        </Stack>
      )}
      {canUpsell && item.upsell_price_id && (
        <Stack
          direction="row"
          className="product-item-upsell"
          sx={{
            alignItems: 'center',
            justifyContent: 'space-between',
            width: '100%',
          }}>
          <Typography
            component="label"
            htmlFor="upsell-switch"
            sx={{
              fontSize: 12,
              cursor: 'pointer',
              color: 'text.secondary',
            }}>
            <Switch
              id="upsell-switch"
              sx={{ mr: 1 }}
              variant="success"
              checked
              onChange={() => onDownsell(item.upsell_price_id)}
            />
            {t('payment.checkout.upsell.revert', {
              recurring: t(`common.${formatRecurring(item.price?.recurring as PriceRecurring)}`),
            })}
          </Typography>
          <Typography component="span" sx={{ fontSize: 12 }}>
            {downsellTokenDisplay ||
              formatPrice(item.price, currency, item.price?.product?.unit_label, 1, true, locale)}
          </Typography>
        </Stack>
      )}
    </Stack>
  );
}
