import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import ArrowForwardIcon from '@mui/icons-material/ArrowForward';
import CreditCardIcon from '@mui/icons-material/CreditCard';
import CurrencyBitcoinIcon from '@mui/icons-material/CurrencyBitcoin';
import ExpandMoreIcon from '@mui/icons-material/ExpandMore';
import HelpOutlineIcon from '@mui/icons-material/HelpOutline';
import LocalOfferOutlinedIcon from '@mui/icons-material/LocalOfferOutlined';
import CloseIcon from '@mui/icons-material/Close';
import LockOutlinedIcon from '@mui/icons-material/LockOutlined';
import {
  Avatar,
  Box,
  Button,
  CircularProgress,
  Collapse,
  Divider,
  Drawer,
  MenuItem,
  Select,
  Skeleton,
  Stack,
  ToggleButton,
  ToggleButtonGroup,
  Tooltip,
  Typography,
} from '@mui/material';
import { useLocaleContext } from '@arcblock/ux/lib/Locale/context';
import {
  useCheckoutStatus,
  usePaymentMethodFeature,
  useCustomerFormFeature,
  useSubmitFeature,
  usePricingFeature,
  useSessionContext,
  useLineItems,
  usePromotion,
  useExchangeRate,
} from '@blocklet/payment-react-headless';
import { joinURL } from 'ufo';
import { usePaymentContext } from '../../../contexts/payment';
import { useMobile } from '../../../hooks/mobile';
import { getPrefix, getStatementDescriptor } from '../../../libs/util';
import OverdueInvoicePayment from '../../../components/over-due-invoice-payment';

import { tSafe, whiteTooltipSx, primaryContrastColor } from '../../utils/format';
import CustomerInfoCard from '../../components/right/customer-info-card';
import SubscriptionDisclaimer from '../../components/right/subscription-disclaimer';
import StatusFeedback from '../../components/right/status-feedback';
import PromotionInput from '../../components/left/promotion-input';

export default function PaymentPanel() {
  const { t, locale } = useLocaleContext();
  const { session, sessionData, subscription, refresh } = useSessionContext();
  const { isDonation } = useCheckoutStatus();
  const paymentMethod = usePaymentMethodFeature();
  const form = useCustomerFormFeature();
  const submit = useSubmitFeature();
  const pricing = usePricingFeature();
  const { session: didSession, connect, prefix: paymentKitPrefix } = usePaymentContext();
  const { inventoryOk } = useLineItems();
  const promotion = usePromotion();
  const rate = useExchangeRate();
  const { isMobile } = useMobile();

  const isAmountLoading = paymentMethod.switching || (rate.hasDynamicPricing && rate.status === 'loading');

  const { currency, types, isStripe, isCrypto } = paymentMethod;
  const mode = session?.mode || 'payment';
  const discounts = (session as any)?.discounts || [];
  const isLoggedIn = !!didSession?.user;
  const actionLabel = isDonation ? t('payment.checkout.donate') : t(`payment.checkout.${mode}`);
  const buttonLabel = isLoggedIn ? actionLabel : t('payment.checkout.connect', { action: actionLabel });

  const [customerLimited, setCustomerLimited] = useState(false);
  const [mobileDetailsOpen, setMobileDetailsOpen] = useState(false);
  const [promoDrawerOpen, setPromoDrawerOpen] = useState(false);

  // Detect CUSTOMER_LIMITED error from submit hook
  useEffect(() => {
    if (submit.status === 'failed' && (submit.context as any)?.code === 'CUSTOMER_LIMITED') {
      setCustomerLimited(true);
    }
  }, [submit.status, submit.context]);

  const canSubmit = submit.status === 'idle' && session?.status === 'open' && inventoryOk;
  const isProcessing = ['submitting', 'waiting_did'].includes(submit.status);

  // Pre-login action handler (mirrors V1 form/index.tsx onAction)
  const handleAction = useCallback(() => {
    if (!canSubmit) return;

    // Lock config to prevent quantity/currency/method changes during submit flow
    submit.lock();

    if (isLoggedIn || isDonation) {
      // Already logged in or donation mode — submit directly
      submit.execute();
      return;
    }

    // Not logged in — initiate DID Connect login first
    didSession?.login?.(() => {
      // After login: refresh session data + re-fetch customer info → then submit
      Promise.all([refresh(true), form.refetchCustomer()])
        .then(() => submit.execute())
        .catch((err) => {
          console.error('Post-login refresh failed:', err);
        });
    });
  }, [canSubmit, isLoggedIn, isDonation, didSession, refresh, form, submit]);

  // When user logs in from top-right (not via handleAction button), refetch customer to fill form
  // Mirrors V1 form/index.tsx useEffect on session?.user
  useEffect(() => {
    if (didSession?.user && !submit.status.startsWith('submitting')) {
      form.refetchCustomer();
    }
  }, [didSession?.user]); // eslint-disable-line react-hooks/exhaustive-deps

  // Group crypto currencies by network (method)
  const cryptoType = types.find((tp) => tp.type === 'crypto');
  const cryptoMethods = useMemo(
    () => paymentMethod.available.filter((m) => m.type !== 'stripe'),
    [paymentMethod.available]
  );
  const networks = useMemo(() => {
    if (!cryptoMethods.length) return [];
    return cryptoMethods.map((m) => ({
      id: m.id,
      name: m.name,
      logo: m.logo || '',
      currencies: m.payment_currencies || [],
    }));
  }, [cryptoMethods]);

  // Current network for dropdown
  const currentMethodId = paymentMethod.current?.id || '';

  // Enter key submit handler
  useEffect(() => {
    const handleKeyDown = (e: KeyboardEvent) => {
      if (e.key === 'Enter' && canSubmit && submit.status === 'idle') {
        const tag = (e.target as HTMLElement)?.tagName?.toLowerCase();
        if (tag === 'textarea') return;
        handleAction();
      }
    };
    document.addEventListener('keydown', handleKeyDown);
    return () => document.removeEventListener('keydown', handleKeyDown);
  }, [canSubmit, submit.status, handleAction]);

  // DID Connect
  const didConnectOpenedRef = useRef(false);
  const didConnectSucceededRef = useRef(false);
  // Track latest submit.status for use inside DID Connect SDK callbacks (onClose/onError),
  // which fire asynchronously and may run after status has already advanced past waiting_did.
  // Reading submit.status directly would capture a stale closure.
  const submitStatusRef = useRef(submit.status);
  useEffect(() => {
    submitStatusRef.current = submit.status;
  }, [submit.status]);
  useEffect(() => {
    if (submit.status !== 'waiting_did') {
      didConnectOpenedRef.current = false;
      didConnectSucceededRef.current = false;
      return;
    }
    const ctx = submit.context;
    if (ctx?.type !== 'did_connect' || !connect) return;
    if (didConnectOpenedRef.current) return;
    didConnectOpenedRef.current = true;

    // Use absolute URL for DID Connect prefix — DID Connect SDK needs full URL
    // for status polling. paymentKitPrefix may be relative ('/' or ''), which can
    // cause polling to fail. getPrefix() from util.ts returns the full origin URL.
    const didPrefix = `${paymentKitPrefix || window.location.origin}/api/did`.replace(/([^:])\/\//g, '$1/');
    connect.open({
      locale: locale as any,
      action: ctx.action,
      prefix: didPrefix,
      saveConnect: false,
      extraParams: ctx.extraParams,
      onSuccess: async () => {
        didConnectSucceededRef.current = true;
        connect.close();
        await submit.didConnectComplete();
      },
      onClose: () => {
        connect.close();
        // If submit has already advanced past waiting_did (e.g. didConnectComplete is
        // polling, or completion/failure resolved), the modal close is a follow-up to a
        // successful flow — do not reset. Without this guard, the effect re-run after
        // setStatus('submitting') clears didConnectSucceededRef, and a late onClose call
        // would incorrectly tear down the in-flight polling.
        if (submitStatusRef.current !== 'waiting_did') return;
        if (!didConnectSucceededRef.current) {
          submit.reset();
        }
      },
      onError: (err: any) => {
        console.error('DID Connect error:', err);
        if (submitStatusRef.current !== 'waiting_did') return;
        submit.reset();
      },
      messages: {
        title: t('payment.checkout.connectModal.title', { action: buttonLabel }),
        scan: t('payment.checkout.connectModal.scan'),
        confirm: t('payment.checkout.connectModal.confirm'),
      } as any,
    });

    // No cleanup needed — connect modal manages its own lifecycle.
  }, [submit.status, submit.context, connect, locale, t, buttonLabel]); // eslint-disable-line react-hooks/exhaustive-deps

  // Active payment type
  const activeType = types.find((tp) => tp.active)?.type || 'crypto';
  const hasMultipleTypes = types.length > 1;

  return (
    <Box sx={{ display: 'flex', flexDirection: 'column', flex: 1, minHeight: 0 }}>
      {/* Main content — scrollable when overflows */}
      <Box
        sx={{
          flex: 1,
          display: 'flex',
          flexDirection: 'column',
          overflowY: 'auto',
          minHeight: 0,
          '&::-webkit-scrollbar': { display: 'none' },
          scrollbarWidth: 'none',
        }}>
        {/* PAYMENT METHOD header */}
        <Typography
          sx={{
            fontSize: 13,
            fontWeight: 700,
            letterSpacing: '0.02em',
            color: 'text.primary',
            mb: 2.5,
          }}>
          {t('payment.checkout.paymentDetails')}
        </Typography>

        {/* Card / Crypto toggle */}
        {hasMultipleTypes && (
          <ToggleButtonGroup
            value={activeType}
            exclusive
            onChange={(_, v) => v && paymentMethod.setType(v)}
            fullWidth
            size="small"
            sx={{
              mb: 2.5,
              bgcolor: (theme) => (theme.palette.mode === 'dark' ? 'rgba(255,255,255,0.06)' : 'grey.100'),
              borderRadius: '10px',
              p: 0.5,
              '& .MuiToggleButton-root': {
                textTransform: 'none',
                borderRadius: '8px !important',
                py: 0.75,
                border: 'none',
                fontSize: 14,
                fontWeight: 500,
                gap: 0.75,
                color: 'text.secondary',
              },
              '& .Mui-selected': {
                bgcolor: 'background.paper !important',
                color: 'text.primary',
                fontWeight: 600,
                boxShadow: (theme) =>
                  theme.palette.mode === 'dark' ? '0 1px 3px rgba(0,0,0,0.3)' : '0 1px 3px rgba(0,0,0,0.08)',
                '&:hover': { bgcolor: 'background.paper !important' },
              },
            }}>
            {types.map((tp) => (
              <ToggleButton key={tp.type} value={tp.type}>
                {tp.type === 'stripe' ? (
                  <CreditCardIcon sx={{ fontSize: 18 }} />
                ) : (
                  <CurrencyBitcoinIcon sx={{ fontSize: 18 }} />
                )}
                {tp.label || (tp.type === 'stripe' ? 'Card' : 'Crypto')}
              </ToggleButton>
            ))}
          </ToggleButtonGroup>
        )}

        {/* Crypto: Network + Asset selectors (side by side) */}
        {isCrypto && networks.length > 0 && (
          <Stack direction="row" spacing={1.5} sx={{ mb: 2.5 }}>
            {/* Network selector */}
            {networks.length > 1 && (
              <Box sx={{ flex: 1 }}>
                <Typography
                  sx={{
                    fontSize: 12,
                    fontWeight: 600,
                    color: 'text.secondary',
                    mb: 0.5,
                    letterSpacing: '0.02em',
                  }}>
                  {t('common.network')}
                </Typography>
                <Select
                  value={currentMethodId}
                  onChange={(e) => {
                    const network = networks.find((n) => n.id === e.target.value);
                    if (network?.currencies?.[0]) {
                      paymentMethod.setCurrency(network.currencies[0].id);
                    }
                  }}
                  fullWidth
                  size="small"
                  sx={{
                    borderRadius: '8px',
                    bgcolor: (theme) => (theme.palette.mode === 'dark' ? 'rgba(255,255,255,0.06)' : 'grey.50'),
                    '& .MuiOutlinedInput-notchedOutline': { borderColor: 'transparent' },
                    '&:hover .MuiOutlinedInput-notchedOutline': { borderColor: 'divider' },
                    '&.Mui-focused .MuiOutlinedInput-notchedOutline': { borderColor: 'primary.main', borderWidth: 1 },
                    '& .MuiSelect-select': { display: 'flex', alignItems: 'center', gap: 1, py: 1 },
                  }}>
                  {networks.map((net) => (
                    <MenuItem key={net.id} value={net.id} sx={{ gap: 1 }}>
                      {net.logo && <Avatar src={net.logo} sx={{ width: 20, height: 20 }} />}
                      <Typography sx={{ fontSize: 14 }}>{net.name}</Typography>
                    </MenuItem>
                  ))}
                </Select>
              </Box>
            )}

            {/* Asset selector */}
            <Box sx={{ flex: 1 }}>
              <Typography
                sx={{
                  fontSize: 12,
                  fontWeight: 600,
                  color: 'text.secondary',
                  mb: 0.5,
                  letterSpacing: '0.02em',
                }}>
                {t('common.currency')}
              </Typography>
              <Select
                value={currency?.id || ''}
                onChange={(e) => paymentMethod.setCurrency(e.target.value as string)}
                fullWidth
                size="small"
                sx={{
                  borderRadius: '8px',
                  bgcolor: (theme) => (theme.palette.mode === 'dark' ? 'rgba(255,255,255,0.06)' : 'grey.50'),
                  '& .MuiOutlinedInput-notchedOutline': { borderColor: 'transparent' },
                  '&:hover .MuiOutlinedInput-notchedOutline': { borderColor: 'divider' },
                  '&.Mui-focused .MuiOutlinedInput-notchedOutline': { borderColor: 'primary.main', borderWidth: 1 },
                  '& .MuiSelect-select': { display: 'flex', alignItems: 'center', gap: 1, py: 1 },
                }}>
                {(isCrypto && networks.length > 1
                  ? networks.find((n) => n.id === currentMethodId)?.currencies || []
                  : cryptoType?.currencies || []
                ).map((cur) => (
                  <MenuItem key={cur.id} value={cur.id} sx={{ gap: 1 }}>
                    {cur.logo && <Avatar src={cur.logo} sx={{ width: 20, height: 20 }} />}
                    <Typography sx={{ fontSize: 14 }}>{cur.symbol}</Typography>
                    <Typography sx={{ fontSize: 12, color: 'text.secondary', ml: 0.5 }}>{cur.name}</Typography>
                  </MenuItem>
                ))}
              </Select>
            </Box>
          </Stack>
        )}

        {/* Card: show currency indicator — same style as crypto asset selector */}
        {isStripe && currency && (
          <Box sx={{ mb: 2.5 }}>
            <Typography
              sx={{
                fontSize: 12,
                fontWeight: 600,
                color: 'text.secondary',
                mb: 0.5,
                letterSpacing: '0.02em',
              }}>
              {t('common.currency')}
            </Typography>
            <Select
              value={currency.id || 'usd'}
              readOnly
              fullWidth
              size="small"
              IconComponent={() => null}
              sx={{
                borderRadius: '8px',
                bgcolor: (theme) => (theme.palette.mode === 'dark' ? 'rgba(255,255,255,0.06)' : 'grey.50'),
                '& .MuiOutlinedInput-notchedOutline': { borderColor: 'transparent !important' },
                '& .MuiSelect-select': { display: 'flex', alignItems: 'center', gap: 1, py: 1 },
              }}>
              <MenuItem value={currency.id || 'usd'} sx={{ gap: 1 }}>
                {currency.logo && <Avatar src={currency.logo} sx={{ width: 20, height: 20 }} />}
                <Typography sx={{ fontSize: 14, fontWeight: 600 }}>{currency.symbol}</Typography>
                <Typography sx={{ fontSize: 12, color: 'text.secondary', ml: 0.5 }}>{currency.name}</Typography>
              </MenuItem>
            </Select>
          </Box>
        )}

        {/* Customer Info */}
        <CustomerInfoCard form={form} isLoggedIn={isLoggedIn} />
      </Box>
      {/* end main content / scrollable area */}

      {/* Submit section — fixed on mobile, flows on desktop */}
      <Box className="cko-v2-submit-btn" sx={{ flexShrink: 0 }}>
        {/* Mobile: collapsible details (staking etc.) */}
        {isMobile && pricing.staking && (
          <>
            <Box
              onClick={() => setMobileDetailsOpen(!mobileDetailsOpen)}
              sx={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', cursor: 'pointer', mb: 1 }}>
              <Typography sx={{ fontSize: 13, fontWeight: 600, color: 'text.secondary' }}>
                {t('payment.checkout.orderSummary')}
              </Typography>
              <ExpandMoreIcon
                sx={{
                  fontSize: 18,
                  color: 'text.secondary',
                  transition: '0.2s',
                  transform: mobileDetailsOpen ? 'rotate(180deg)' : 'rotate(0deg)',
                }}
              />
            </Box>
            <Collapse in={mobileDetailsOpen}>
              <Stack direction="row" justifyContent="space-between" alignItems="center" sx={{ mb: 1 }}>
                <Stack direction="row" spacing={0.5} alignItems="center">
                  <Typography sx={{ fontSize: 13, color: 'text.secondary' }}>
                    {t('payment.checkout.staking.title')}
                  </Typography>
                  <HelpOutlineIcon sx={{ fontSize: 14, color: 'text.disabled' }} />
                </Stack>
                {isAmountLoading ? (
                  <Skeleton variant="text" width={60} height={18} />
                ) : (
                  <Typography sx={{ fontSize: 13, fontWeight: 600 }}>+{pricing.staking}</Typography>
                )}
              </Stack>
              <Divider sx={{ mb: 1 }} />
            </Collapse>
          </>
        )}

        {/* Desktop: staking + promotion (together with Total Due) */}
        {!isMobile && (
          <>
            <Divider sx={{ mb: 2 }} />
            {pricing.staking && (
              <Stack direction="row" justifyContent="space-between" alignItems="center" sx={{ mb: 1 }}>
                <Stack direction="row" spacing={0.5} alignItems="center">
                  <Typography sx={{ fontSize: 14, color: 'text.secondary' }}>
                    {t('payment.checkout.staking.title')}
                  </Typography>
                  <Tooltip
                    title={t('payment.checkout.staking.tooltip')}
                    placement="top"
                    arrow
                    slotProps={{ popper: { sx: whiteTooltipSx } }}>
                    <HelpOutlineIcon sx={{ fontSize: 16, color: 'text.disabled' }} />
                  </Tooltip>
                </Stack>
                {isAmountLoading ? (
                  <Skeleton variant="text" width={80} height={22} />
                ) : (
                  <Typography sx={{ fontSize: 14, fontWeight: 600 }}>+{pricing.staking}</Typography>
                )}
              </Stack>
            )}
            <PromotionInput
              promotion={{
                applied: promotion.applied,
                code: promotion.code,
                active: promotion.active,
                inactiveReason: promotion.inactiveReason,
                apply: promotion.apply,
                remove: promotion.remove,
              }}
              discounts={discounts}
              discountAmount={pricing.discount}
              currency={currency}
              isAmountLoading={isAmountLoading}
            />
          </>
        )}

        {/* Total amount due */}
        {(() => {
          const totalStr = pricing.total || '0';
          const parts = totalStr.split(/\s+/);
          const num = parts[0] || '0';
          const sym = parts.slice(1).join(' ') || currency?.symbol || '';
          const dotIdx = num.indexOf('.');
          const intPart = dotIdx >= 0 ? num.slice(0, dotIdx) : num;
          const decPart = dotIdx >= 0 ? num.slice(dotIdx) : '';
          return (
            <Box sx={{ mb: isMobile ? 1.5 : 2.5 }}>
              <Stack direction="row" justifyContent="space-between" alignItems="flex-end">
                <Typography sx={{ fontWeight: 700, fontSize: 14, color: 'text.secondary', pb: 0.5 }}>
                  {t('common.totalDue')}
                </Typography>
                {isAmountLoading ? (
                  <Skeleton variant="text" width={140} height={44} />
                ) : (
                  <Box sx={{ textAlign: 'right' }}>
                    <Typography
                      component="span"
                      sx={{
                        fontSize: { xs: 28, md: 36 },
                        fontWeight: 800,
                        color: 'text.primary',
                        lineHeight: 1,
                        transition: 'opacity 0.3s ease',
                      }}>
                      {intPart}
                    </Typography>
                    {decPart && (
                      <Typography
                        component="span"
                        sx={{ fontSize: { xs: 16, md: 20 }, fontWeight: 700, color: 'text.secondary', lineHeight: 1 }}>
                        {decPart}
                      </Typography>
                    )}
                    <Typography
                      component="span"
                      sx={{ fontSize: { xs: 14, md: 16 }, fontWeight: 600, color: 'text.secondary', ml: 0.75 }}>
                      {sym}
                    </Typography>
                  </Box>
                )}
              </Stack>
              {/* Row below Total Due: mobile promo (left) + USD estimate (right) */}
              {(pricing.usdEquivalent || (isMobile && promotion.active)) && !isAmountLoading && (
                <Stack direction="row" justifyContent="space-between" alignItems="center" sx={{ mt: 0.25 }}>
                  {/* Mobile: promo link or applied badge — left-aligned */}
                  {(() => {
                    if (isMobile && !promotion.applied && promotion.active) {
                      return (
                        <Box
                          onClick={() => setPromoDrawerOpen(true)}
                          sx={{ display: 'flex', alignItems: 'center', gap: 0.5, cursor: 'pointer' }}>
                          <LocalOfferOutlinedIcon sx={{ fontSize: 14, color: 'primary.main' }} />
                          <Typography sx={{ fontSize: 12, fontWeight: 600, color: 'primary.main' }}>
                            {tSafe(t, 'payment.checkout.promotion.add', 'Add promo code')}
                          </Typography>
                        </Box>
                      );
                    }
                    if (isMobile && promotion.applied) {
                      return (
                        <Stack direction="row" alignItems="center" spacing={0.5}>
                          <LocalOfferOutlinedIcon sx={{ fontSize: 14, color: 'success.main' }} />
                          <Typography sx={{ fontSize: 12, fontWeight: 600, color: 'success.main' }}>
                            {promotion.code}
                          </Typography>
                          {pricing.discount && (
                            <Typography sx={{ fontSize: 11, color: 'text.secondary' }}>
                              (-{pricing.discount})
                            </Typography>
                          )}
                          <CloseIcon
                            onClick={promotion.remove}
                            sx={{ fontSize: 14, color: 'error.main', cursor: 'pointer', ml: 0.25 }}
                          />
                        </Stack>
                      );
                    }
                    return <Box />;
                  })()}
                  {/* USD estimate — right-aligned */}
                  {pricing.usdEquivalent && (
                    <Typography sx={{ fontSize: 13, color: 'text.secondary' }}>≈ {pricing.usdEquivalent}</Typography>
                  )}
                </Stack>
              )}
            </Box>
          );
        })()}

        {/* Submit button */}
        <Button
          variant="contained"
          size="large"
          fullWidth
          disabled={!canSubmit || submit.status === 'waiting_stripe'}
          onClick={handleAction}
          startIcon={isProcessing ? <CircularProgress size={20} color="inherit" /> : null}
          sx={{
            py: 1.5,
            fontSize: '1.1rem',
            fontWeight: 600,
            textTransform: 'none',
            borderRadius: '12px',
            color: (theme) => primaryContrastColor(theme),
            position: 'relative',
            overflow: 'hidden',
            '&:hover': { bgcolor: 'primary.main' },
            '&:hover .arrow-icon': { transform: 'translateX(4px)' },
            '&:hover .shine-layer': { transform: 'translateX(100%)' },
          }}>
          <Box component="span" sx={{ position: 'relative', zIndex: 1 }}>
            {isProcessing ? `${t('payment.checkout.processing')}...` : buttonLabel}
          </Box>
          {!isProcessing && (
            <ArrowForwardIcon
              className="arrow-icon"
              sx={{ ml: 1, position: 'relative', zIndex: 1, transition: 'transform 0.2s ease' }}
            />
          )}
          <Box
            className="shine-layer"
            sx={{
              position: 'absolute',
              inset: 0,
              background: 'linear-gradient(90deg, transparent, rgba(255,255,255,0.12), transparent)',
              transform: 'translateX(-100%)',
              transition: 'transform 0.7s ease',
              pointerEvents: 'none',
            }}
          />
        </Button>

        {/* Mobile: SSL footer inside fixed bar, below button */}
        {isMobile && (
          <Stack
            direction="row"
            alignItems="center"
            justifyContent="center"
            spacing={0.75}
            sx={{ mt: 1.5, opacity: 0.55 }}>
            <LockOutlinedIcon sx={{ fontSize: 13, color: 'text.secondary' }} />
            <Typography sx={{ fontSize: 11, color: 'text.secondary' }}>
              {tSafe(t, 'payment.checkout.ssl', 'SSL Secure')}
            </Typography>
            <Typography sx={{ fontSize: 11, color: 'text.disabled' }}>·</Typography>
            <Typography sx={{ fontSize: 11, color: 'text.secondary' }}>{tSafe(t, 'common.terms', 'Terms')}</Typography>
            <Typography sx={{ fontSize: 11, color: 'text.disabled' }}>|</Typography>
            <Typography sx={{ fontSize: 11, color: 'text.secondary' }}>
              {tSafe(t, 'common.privacy', 'Privacy')}
            </Typography>
          </Stack>
        )}
      </Box>
      {/* end submit fixed bar */}

      {/* Mobile: Promo code drawer */}
      {isMobile && (
        <Drawer
          anchor="bottom"
          open={promoDrawerOpen}
          onClose={() => setPromoDrawerOpen(false)}
          PaperProps={{
            sx: {
              borderRadius: '16px 16px 0 0',
              p: 3,
              pb: 4,
              minHeight: '30vh',
            },
          }}>
          <Box sx={{ width: 40, height: 4, bgcolor: 'divider', borderRadius: 2, mx: 'auto', mb: 3 }} />
          <Typography sx={{ fontWeight: 700, fontSize: 16, mb: 2 }}>
            {tSafe(t, 'payment.checkout.promotion.add', 'Add promo code')}
          </Typography>
          <PromotionInput
            initialShowInput
            promotion={{
              applied: promotion.applied,
              code: promotion.code,
              active: promotion.active,
              inactiveReason: promotion.inactiveReason,
              apply: async (...args: Parameters<typeof promotion.apply>) => {
                const result = await promotion.apply(...args);
                if (result.success) setPromoDrawerOpen(false);
                return result;
              },
              remove: promotion.remove,
            }}
            discounts={discounts}
            discountAmount={pricing.discount}
            currency={currency}
          />
        </Drawer>
      )}

      {/* Disclaimer + footer — outside fixed bar, desktop only for SSL */}
      <Box sx={{ flexShrink: 0 }}>
        <SubscriptionDisclaimer
          mode={mode}
          subscription={subscription}
          staking={pricing.staking}
          appName={getStatementDescriptor(session?.line_items || [])}
        />

        {!isMobile && (
          <Stack
            direction="row"
            alignItems="center"
            justifyContent="center"
            spacing={0.75}
            sx={{ mt: 2.5, opacity: 0.55 }}>
            <LockOutlinedIcon sx={{ fontSize: 13, color: 'text.secondary' }} />
            <Typography sx={{ fontSize: 11, color: 'text.secondary' }}>
              {tSafe(t, 'payment.checkout.ssl', 'SSL Secure')}
            </Typography>
            <Typography sx={{ fontSize: 11, color: 'text.disabled' }}>·</Typography>
            <Typography sx={{ fontSize: 11, color: 'text.secondary' }}>{tSafe(t, 'common.terms', 'Terms')}</Typography>
            <Typography sx={{ fontSize: 11, color: 'text.disabled' }}>|</Typography>
            <Typography sx={{ fontSize: 11, color: 'text.secondary' }}>
              {tSafe(t, 'common.privacy', 'Privacy')}
            </Typography>
          </Stack>
        )}
      </Box>

      {/* Status Feedback (Toast errors only — dialogs handled by CheckoutDialogs) */}
      <StatusFeedback status={submit.status} context={submit.context} onReset={submit.reset} />

      {/* Overdue Invoice Payment (CUSTOMER_LIMITED) */}
      {customerLimited && (
        <OverdueInvoicePayment
          customerId={(sessionData as any)?.customer?.id || (session as any)?.user?.did}
          onPaid={() => {
            setCustomerLimited(false);
            submit.retry();
          }}
          alertMessage={t('payment.customer.pastDue.alert.customMessage')}
          detailLinkOptions={{
            enabled: true,
            onClick: () => {
              setCustomerLimited(false);
              window.open(
                joinURL(getPrefix(), `/customer/invoice/past-due?referer=${encodeURIComponent(window.location.href)}`),
                '_self'
              );
            },
          }}
          dialogProps={{
            open: customerLimited,
            onClose: () => {
              setCustomerLimited(false);
              submit.reset();
            },
            title: t('payment.customer.pastDue.alert.title'),
          }}
        />
      )}
    </Box>
  );
}
