import React, { useCallback, useEffect, useMemo, useState } from 'react';
import styled from 'styled-components';
import { axiosInstance } from '../../../axiosApi';
import { AnalyticsEvents, trackEvent } from '../../utils/analytics';
import {
  canOpenBillingPortal,
  checkoutReturnUrls,
  FinanceInvoice,
  FinancePayment,
  formatBillingDate,
  formatMoneyCents,
  formatTokenCount,
  higherSelectablePlans,
  humanizeStatus,
  invoiceProviderLabel,
  isComplimentarySubscription,
  isStoreSubscription,
  isStripeSubscription,
  otherSelectablePlans,
  pickPrimaryInvoice,
  SubscriptionMe,
  SubscriptionPlanInfo,
} from '../../utils/finance';
import { isNativePlatform } from '../../platform/nativePlatform';
import {
  isPurchaseCancelledError,
  purchasePlan,
  restorePurchases,
} from '../../utils/revenueCat';

const GlassCard = styled.div`
  background: ${({ theme }) => theme.colors.cardBackground};
  backdrop-filter: blur(10px);
  border: 1px solid ${({ theme }) => theme.colors.cardBorder};
  border-radius: 1rem;
  padding: 2rem;
  width: 100%;
  max-width: 1000px;
  margin-bottom: 2rem;
  box-shadow: 0 8px 32px 0 rgba(0, 0, 0, 0.37);
`;

const CardTitle = styled.h2`
  font-size: 1.8rem;
  margin-bottom: 1.5rem;
  color: ${({ theme }) => theme.colors.text};
  border-bottom: 1px solid ${({ theme }) => theme.colors.cardBorder};
  padding-bottom: 1rem;
`;

const SettingRow = styled.div`
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 1rem;
  padding: 1rem 0;
  border-bottom: 1px solid ${({ theme }) => theme.colors.cardBorder};

  &:last-child {
    border-bottom: none;
  }
`;

const SettingLabel = styled.span`
  font-size: 1.1rem;
  color: ${({ theme }) => theme.colors.text};
  font-weight: 500;
  opacity: 0.75;
`;

const SettingValue = styled.span`
  font-size: 1.1rem;
  color: ${({ theme }) => theme.colors.text};
  font-weight: 600;
  text-align: right;
`;

const BodyText = styled.p`
  color: ${({ theme }) => theme.colors.text};
  opacity: 0.75;
  margin: 0 0 1rem 0;
  line-height: 1.5;
`;

const NoticeText = styled.p`
  color: ${({ theme }) => theme.colors.text};
  opacity: 0.85;
  margin: 1rem 0 0 0;
  line-height: 1.5;
  font-size: 0.95rem;
`;

const ErrorText = styled.p`
  color: #ff6b6b;
  margin: 0.75rem 0 0 0;
  font-size: 0.95rem;
`;

const ButtonRow = styled.div`
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
  margin-top: 1.25rem;
`;

const StyledButton = styled.button`
  background: ${({ theme }) => theme.main};
  border: none;
  border-radius: 0.5rem;
  color: #fff;
  padding: 0.8rem 1.5rem;
  font-weight: 600;
  cursor: pointer;
  transition: transform 0.2s ease, box-shadow 0.2s ease;

  &:hover {
    transform: translateY(-2px);
    box-shadow: 0 4px 12px ${({ theme }) => theme.main}66;
  }

  &:disabled {
    opacity: 0.5;
    cursor: not-allowed;
    transform: none;
    box-shadow: none;
  }
`;

const SecondaryButton = styled(StyledButton)`
  background: transparent;
  border: 1px solid ${({ theme }) => theme.colors.cardBorder};
  color: ${({ theme }) => theme.colors.text};

  &:hover {
    box-shadow: none;
    border-color: ${({ theme }) => theme.main};
  }
`;

const DangerButton = styled(SecondaryButton)`
  border-color: #ff6b6b66;
  color: #ff6b6b;

  &:hover {
    border-color: #ff6b6b;
  }
`;

const PlanList = styled.ul`
  list-style: none;
  margin: 1rem 0 0 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
`;

const PlanOption = styled.li`
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  align-items: center;
  gap: 0.75rem;
  padding: 1rem;
  border: 1px solid ${({ theme }) => theme.colors.cardBorder};
  border-radius: 0.75rem;
`;

const PlanMeta = styled.div`
  flex: 1;
  min-width: 200px;
`;

const PlanName = styled.div`
  font-weight: 600;
  color: ${({ theme }) => theme.colors.text};
  margin-bottom: 0.25rem;
`;

const PlanDesc = styled.div`
  font-size: 0.9rem;
  color: ${({ theme }) => theme.colors.text};
  opacity: 0.7;
  line-height: 1.4;
`;

const ModalBackdrop = styled.div`
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.55);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 1000;
  padding: 1.5rem;
`;

const ModalCard = styled.div`
  background: ${({ theme }) => theme.colors.cardBackground};
  backdrop-filter: blur(12px);
  border: 1px solid ${({ theme }) => theme.colors.cardBorder};
  border-radius: 1rem;
  padding: 1.75rem;
  max-width: 480px;
  width: 100%;
  box-shadow: 0 12px 40px rgba(0, 0, 0, 0.45);
`;

const ModalTitle = styled.h3`
  margin: 0 0 0.75rem 0;
  color: ${({ theme }) => theme.colors.text};
  font-size: 1.35rem;
`;

const StyledTable = styled.table`
  width: 100%;
  border-collapse: collapse;
  margin-top: 1rem;
`;

const Th = styled.th`
  text-align: left;
  padding: 1rem;
  border-bottom: 1px solid ${({ theme }) => theme.colors.cardBorder};
  color: ${({ theme }) => theme.colors.text};
  opacity: 0.7;
  font-weight: 600;
`;

const Td = styled.td`
  padding: 1rem;
  border-bottom: 1px solid ${({ theme }) => theme.colors.cardBorder};
  color: ${({ theme }) => theme.colors.text};
`;

const InvoiceLink = styled.a`
  color: ${({ theme }) => theme.main};
  text-decoration: none;

  &:hover {
    text-decoration: underline;
  }
`;

const ProviderBadge = styled.span`
  display: inline-block;
  font-size: 0.8rem;
  font-weight: 600;
  opacity: 0.85;
  white-space: nowrap;
`;

function apiErrorMessage(error: unknown, fallback: string): string {
  const axiosError = error as {
    response?: { data?: { detail?: string } };
    message?: string;
  };
  return axiosError.response?.data?.detail || axiosError.message || fallback;
}

function storeManageLabel(): string {
  if (typeof window === 'undefined') return 'App Store / Play Store';
  const Cap = window.Capacitor as { getPlatform?: () => string } | undefined;
  const platform = Cap?.getPlatform?.();
  if (platform === 'ios') return 'App Store';
  if (platform === 'android') return 'Play Store';
  return 'App Store / Play Store';
}

type PortalIntent = 'manage' | 'upgrade' | 'change' | 'cancel';

const BillingSection = (): JSX.Element => {
  const native = isNativePlatform();
  const [invoices, setInvoices] = useState<FinanceInvoice[]>([]);
  const [payments, setPayments] = useState<FinancePayment[]>([]);
  const [subscription, setSubscription] = useState<SubscriptionMe | null>(null);
  const [plans, setPlans] = useState<SubscriptionPlanInfo[]>([]);
  const [loading, setLoading] = useState(true);
  const [listError, setListError] = useState('');
  const [actionError, setActionError] = useState('');
  const [actionNotice, setActionNotice] = useState('');
  const [portalLoading, setPortalLoading] = useState(false);
  const [checkoutLoadingSlug, setCheckoutLoadingSlug] = useState<string | null>(null);
  const [restoreLoading, setRestoreLoading] = useState(false);
  const [showPlanPicker, setShowPlanPicker] = useState(false);
  const [planPickerMode, setPlanPickerMode] = useState<'upgrade' | 'change'>('change');
  const [cancelConfirmOpen, setCancelConfirmOpen] = useState(false);

  const loadBilling = useCallback(async () => {
    setLoading(true);
    setListError('');
    try {
      const [invoiceResponse, paymentResponse, subscriptionResponse, plansResponse] =
        await Promise.all([
          axiosInstance.get<FinanceInvoice[]>('/monetization/invoices/'),
          axiosInstance.get<FinancePayment[]>('/monetization/payments/'),
          axiosInstance.get<SubscriptionMe>('/monetization/subscription/'),
          axiosInstance.get<SubscriptionPlanInfo[]>('/monetization/plans/'),
        ]);
      setInvoices(Array.isArray(invoiceResponse.data) ? invoiceResponse.data : []);
      setPayments(Array.isArray(paymentResponse.data) ? paymentResponse.data : []);
      setSubscription(subscriptionResponse.data || null);
      setPlans(Array.isArray(plansResponse.data) ? plansResponse.data : []);
    } catch (error: unknown) {
      setInvoices([]);
      setPayments([]);
      setSubscription(null);
      setPlans([]);
      setListError(apiErrorMessage(error, 'Could not load billing information.'));
    } finally {
      setLoading(false);
    }
  }, []);

  useEffect(() => {
    loadBilling();
  }, [loadBilling]);

  const primaryInvoice = useMemo(() => pickPrimaryInvoice(invoices), [invoices]);
  const hasPortalAccess = useMemo(() => canOpenBillingPortal(invoices), [invoices]);
  const complimentary = useMemo(
    () => isComplimentarySubscription(subscription, hasPortalAccess),
    [subscription, hasPortalAccess]
  );
  const storeSub = useMemo(
    () => isStoreSubscription(subscription?.source),
    [subscription?.source]
  );
  const stripeSub = useMemo(
    () => isStripeSubscription(subscription?.source) || hasPortalAccess,
    [subscription?.source, hasPortalAccess]
  );
  const showStripeManage = !complimentary && stripeSub && hasPortalAccess;
  const showStoreManage = !complimentary && (storeSub || (native && !showStripeManage && Boolean(subscription?.plan) && !subscription?.needs_checkout));
  const upgradePlans = useMemo(
    () => higherSelectablePlans(plans, subscription?.plan),
    [plans, subscription?.plan]
  );
  const changePlans = useMemo(
    () => otherSelectablePlans(plans, subscription?.plan?.slug),
    [plans, subscription?.plan?.slug]
  );
  const periodEndLabel = useMemo(() => {
    const end =
      subscription?.current_period_end || primaryInvoice?.period_end || null;
    return formatBillingDate(end);
  }, [subscription?.current_period_end, primaryInvoice?.period_end]);
  const storeLabel = useMemo(() => storeManageLabel(), []);

  const historyRows = useMemo(() => {
    if (invoices.length) {
      return invoices.map((invoice) => ({
        key: `invoice-${invoice.id}`,
        date: invoice.created,
        description: invoice.description || 'Invoice',
        provider: invoiceProviderLabel(invoice),
        amount: formatMoneyCents(
          invoice.amount_paid || invoice.amount_due,
          invoice.currency
        ),
        status: humanizeStatus(invoice.status),
        url: invoice.hosted_invoice_url || '',
      }));
    }
    return payments.map((payment) => ({
      key: `payment-${payment.id}`,
      date: payment.paid_at || payment.created,
      description: 'Payment',
      provider:
        (payment.provider || '').toLowerCase() === 'revenuecat'
          ? 'Store'
          : (payment.provider || '').toLowerCase() === 'stripe'
            ? 'Stripe'
            : payment.provider || '—',
      amount: formatMoneyCents(payment.amount, payment.currency),
      status: humanizeStatus(payment.status),
      url: '',
    }));
  }, [invoices, payments]);

  const openPortal = async (intent: PortalIntent) => {
    setActionError('');
    setActionNotice('');
    setPortalLoading(true);
    try {
      const returnUrl = `${window.location.origin}/account/`;
      const response = await axiosInstance.post<{ portal_url: string }>(
        '/monetization/portal/',
        { return_url: returnUrl }
      );
      const portalUrl = response.data?.portal_url;
      if (!portalUrl) {
        setActionError('Billing portal could not be opened. Try again.');
        return;
      }
      trackEvent(AnalyticsEvents.BILLING_PORTAL_OPENED, { intent });
      window.location.assign(portalUrl);
    } catch (error: unknown) {
      setActionError(
        apiErrorMessage(error, 'Could not open the billing portal. Try again.')
      );
    } finally {
      setPortalLoading(false);
    }
  };

  const handleNativePurchase = async (planSlug?: string, source = 'account_billing') => {
    setActionError('');
    setActionNotice('');
    setCheckoutLoadingSlug(planSlug || '__default__');
    try {
      trackEvent(AnalyticsEvents.CHECKOUT_STARTED, {
        source,
        ...(planSlug ? { plan_slug: planSlug } : {}),
      });
      await purchasePlan(planSlug);
      setActionNotice(
        'Purchase submitted. Entitlements update after the store confirms — tap Refresh shortly.'
      );
      await loadBilling();
    } catch (error: unknown) {
      if (isPurchaseCancelledError(error)) {
        setActionNotice('Purchase cancelled.');
        return;
      }
      setActionError(
        apiErrorMessage(error, 'Store purchase failed. Try again or Restore purchases.')
      );
    } finally {
      setCheckoutLoadingSlug(null);
    }
  };

  const handleRestore = async () => {
    setActionError('');
    setActionNotice('');
    setRestoreLoading(true);
    try {
      await restorePurchases();
      setActionNotice('Purchases restored. Refreshing billing…');
      await loadBilling();
    } catch (error: unknown) {
      setActionError(apiErrorMessage(error, 'Could not restore purchases. Try again.'));
    } finally {
      setRestoreLoading(false);
    }
  };

  const handleStartCheckout = async (planSlug?: string, source = 'account_billing') => {
    if (native) {
      await handleNativePurchase(planSlug, source);
      return;
    }
    setActionError('');
    setActionNotice('');
    setCheckoutLoadingSlug(planSlug || '__default__');
    try {
      const { success_url, cancel_url } = checkoutReturnUrls();
      trackEvent(AnalyticsEvents.CHECKOUT_STARTED, {
        source,
        ...(planSlug ? { plan_slug: planSlug } : {}),
      });
      const response = await axiosInstance.post<{ checkout_url: string }>(
        '/monetization/checkout/',
        {
          success_url,
          cancel_url,
          ...(planSlug ? { plan_slug: planSlug } : {}),
        }
      );
      const checkoutUrl = response.data?.checkout_url;
      if (!checkoutUrl) {
        setActionError('Checkout could not be started. Try again.');
        return;
      }
      window.location.assign(checkoutUrl);
    } catch (error: unknown) {
      setActionError(apiErrorMessage(error, 'Could not start checkout. Try again.'));
    } finally {
      setCheckoutLoadingSlug(null);
    }
  };

  const handleUpgradeClick = () => {
    trackEvent(AnalyticsEvents.SUBSCRIPTION_UPGRADE_STARTED, {
      source: 'account_billing',
    });
    if (upgradePlans.length > 0) {
      setPlanPickerMode('upgrade');
      setShowPlanPicker(true);
      return;
    }
    if (native && (storeSub || showStoreManage)) {
      void handleNativePurchase(undefined, 'account_upgrade');
      return;
    }
    void openPortal('upgrade');
  };

  const handleChangePlanClick = () => {
    trackEvent(AnalyticsEvents.PLAN_CHANGE_STARTED, { source: 'account_billing' });
    if (changePlans.length > 0) {
      setPlanPickerMode('change');
      setShowPlanPicker(true);
      return;
    }
    if (native && (storeSub || showStoreManage)) {
      setActionNotice(
        `Change or cancel your plan in ${storeLabel} subscription settings.`
      );
      return;
    }
    void openPortal('change');
  };

  const handleConfirmCancel = async () => {
    if (native && (storeSub || showStoreManage) && !showStripeManage) {
      trackEvent(AnalyticsEvents.SUBSCRIPTION_CANCEL_STARTED, { source: 'store' });
      setCancelConfirmOpen(false);
      setActionNotice(
        `Open ${storeLabel} → Subscriptions to cancel. Access usually continues until the period end.`
      );
      return;
    }
    trackEvent(AnalyticsEvents.SUBSCRIPTION_CANCEL_STARTED, { source: 'portal' });
    setCancelConfirmOpen(false);
    await openPortal('cancel');
  };

  const pickerPlans = planPickerMode === 'upgrade' ? upgradePlans : changePlans;

  const selectPlanFromPicker = async (plan: SubscriptionPlanInfo) => {
    if (planPickerMode === 'upgrade') {
      trackEvent(AnalyticsEvents.SUBSCRIPTION_UPGRADE_STARTED, {
        source: 'plan_picker',
        plan_slug: plan.slug,
      });
      await handleStartCheckout(plan.slug, 'account_upgrade');
      return;
    }
    trackEvent(AnalyticsEvents.PLAN_CHANGE_STARTED, {
      source: 'plan_picker',
      plan_slug: plan.slug,
    });
    if (native && (storeSub || showStoreManage) && !showStripeManage) {
      setShowPlanPicker(false);
      await handleNativePurchase(plan.slug, 'account_change');
      return;
    }
    // Existing Stripe subscribers change plans in the portal (proration / PCI).
    setShowPlanPicker(false);
    await openPortal('change');
  };

  return (
    <>
      <GlassCard data-testid="billing-section">
        <CardTitle>Billing</CardTitle>
        {loading ? (
          <BodyText>Loading billing information…</BodyText>
        ) : listError ? (
          <ErrorText role="alert">{listError}</ErrorText>
        ) : subscription?.plan || primaryInvoice ? (
          <>
            <SettingRow>
              <SettingLabel>Plan</SettingLabel>
              <SettingValue>
                {subscription?.plan?.name ||
                  primaryInvoice?.description ||
                  'Chat Subscription'}
              </SettingValue>
            </SettingRow>
            <SettingRow>
              <SettingLabel>Status</SettingLabel>
              <SettingValue>
                {humanizeStatus(subscription?.status || primaryInvoice?.status || 'none')}
              </SettingValue>
            </SettingRow>
            {subscription?.plan ? (
              <SettingRow>
                <SettingLabel>Price</SettingLabel>
                <SettingValue>
                  {formatMoneyCents(
                    subscription.plan.price_cents,
                    subscription.plan.currency
                  )}
                  {subscription.plan.interval ? ` / ${subscription.plan.interval}` : ''}
                </SettingValue>
              </SettingRow>
            ) : primaryInvoice ? (
              <SettingRow>
                <SettingLabel>Amount</SettingLabel>
                <SettingValue>
                  {formatMoneyCents(
                    primaryInvoice.amount_paid || primaryInvoice.amount_due,
                    primaryInvoice.currency
                  )}
                  {primaryInvoice.period_end ? ' / period' : ''}
                </SettingValue>
              </SettingRow>
            ) : null}
            {subscription?.usage ? (
              <>
                <SettingRow>
                  <SettingLabel>Prompts remaining</SettingLabel>
                  <SettingValue>
                    {subscription.usage.prompts_remaining === null
                      ? '—'
                      : `${subscription.usage.prompts_remaining} / ${subscription.usage.prompt_quota} (${subscription.usage.window_hours}h)`}
                  </SettingValue>
                </SettingRow>
                <SettingRow>
                  <SettingLabel>Tokens this period</SettingLabel>
                  <SettingValue>
                    in {formatTokenCount(subscription.usage.tokens_in_period)} · out{' '}
                    {formatTokenCount(subscription.usage.tokens_out_period)}
                  </SettingValue>
                </SettingRow>
              </>
            ) : null}
            <SettingRow>
              <SettingLabel>Period end</SettingLabel>
              <SettingValue>{periodEndLabel}</SettingValue>
            </SettingRow>
            {subscription?.cancel_at_period_end ? (
              <NoticeText data-testid="cancel-scheduled-notice">
                Cancellation scheduled. You keep access until {periodEndLabel}.
              </NoticeText>
            ) : null}
            {subscription?.status === 'canceled' ? (
              <NoticeText>
                Subscription canceled. Renew via Complete payment when you are ready.
              </NoticeText>
            ) : null}
          </>
        ) : (
          <BodyText>
            No active subscription yet. Complete payment to unlock billing management
            and invoice history.
          </BodyText>
        )}

        {!loading && !listError && (
          <ButtonRow>
            {showStripeManage ? (
              <>
                <StyledButton
                  type="button"
                  onClick={handleUpgradeClick}
                  disabled={portalLoading || Boolean(checkoutLoadingSlug)}
                >
                  Upgrade
                </StyledButton>
                <SecondaryButton
                  type="button"
                  onClick={handleChangePlanClick}
                  disabled={portalLoading || Boolean(checkoutLoadingSlug)}
                >
                  Change plan
                </SecondaryButton>
                {!subscription?.cancel_at_period_end &&
                subscription?.status !== 'canceled' ? (
                  <DangerButton
                    type="button"
                    onClick={() => setCancelConfirmOpen(true)}
                    disabled={portalLoading}
                  >
                    Cancel
                  </DangerButton>
                ) : null}
                <SecondaryButton
                  type="button"
                  onClick={() => openPortal('manage')}
                  disabled={portalLoading}
                >
                  {portalLoading ? 'Opening…' : 'Manage subscription'}
                </SecondaryButton>
              </>
            ) : complimentary ? (
              <BodyText style={{ margin: 0 }} data-testid="complimentary-billing-message">
                Complimentary access — no payment required. Plan changes and
                cancellation are not available for this account.
              </BodyText>
            ) : showStoreManage ? (
              <>
                <StyledButton
                  type="button"
                  onClick={handleUpgradeClick}
                  disabled={Boolean(checkoutLoadingSlug) || restoreLoading}
                >
                  Upgrade
                </StyledButton>
                <SecondaryButton
                  type="button"
                  onClick={handleChangePlanClick}
                  disabled={Boolean(checkoutLoadingSlug) || restoreLoading}
                >
                  Change plan
                </SecondaryButton>
                {!subscription?.cancel_at_period_end &&
                subscription?.status !== 'canceled' ? (
                  <DangerButton
                    type="button"
                    onClick={() => setCancelConfirmOpen(true)}
                    disabled={Boolean(checkoutLoadingSlug)}
                  >
                    Cancel
                  </DangerButton>
                ) : null}
                <SecondaryButton
                  type="button"
                  onClick={() =>
                    setActionNotice(
                      `Manage billing in ${storeLabel} → Subscriptions. Changes sync here after refresh.`
                    )
                  }
                  data-testid="store-manage-hint"
                >
                  Manage in {storeLabel}
                </SecondaryButton>
                {native ? (
                  <SecondaryButton
                    type="button"
                    onClick={handleRestore}
                    disabled={restoreLoading || Boolean(checkoutLoadingSlug)}
                    data-testid="restore-purchases"
                  >
                    {restoreLoading ? 'Restoring…' : 'Restore purchases'}
                  </SecondaryButton>
                ) : null}
              </>
            ) : (
              <>
                <StyledButton
                  type="button"
                  onClick={() => handleStartCheckout()}
                  disabled={Boolean(checkoutLoadingSlug) || restoreLoading}
                >
                  {checkoutLoadingSlug ? 'Starting…' : 'Complete payment'}
                </StyledButton>
                {native ? (
                  <SecondaryButton
                    type="button"
                    onClick={handleRestore}
                    disabled={restoreLoading || Boolean(checkoutLoadingSlug)}
                    data-testid="restore-purchases"
                  >
                    {restoreLoading ? 'Restoring…' : 'Restore purchases'}
                  </SecondaryButton>
                ) : null}
              </>
            )}
            <SecondaryButton type="button" onClick={loadBilling} disabled={loading}>
              Refresh
            </SecondaryButton>
          </ButtonRow>
        )}

        {showPlanPicker && pickerPlans.length > 0 ? (
          <div data-testid="plan-picker">
            <BodyText style={{ marginTop: '1.25rem', marginBottom: 0 }}>
              {planPickerMode === 'upgrade'
                ? native && !showStripeManage
                  ? 'Choose a higher plan. Purchase completes in the app store.'
                  : 'Choose a higher plan. Checkout opens securely in Stripe.'
                : native && !showStripeManage
                  ? 'Select another plan to purchase via the app store.'
                  : 'Select another plan, then confirm the change in the Stripe customer portal (price and quotas update there).'}
            </BodyText>
            <PlanList>
              {pickerPlans.map((plan) => (
                <PlanOption key={plan.slug}>
                  <PlanMeta>
                    <PlanName>{plan.name}</PlanName>
                    <PlanDesc>
                      {formatMoneyCents(plan.price_cents, plan.currency)}
                      {plan.interval ? ` / ${plan.interval}` : ''}
                      {plan.description ? ` — ${plan.description}` : ''}
                      {` · ${plan.prompt_quota_per_window} prompts / ${plan.prompt_window_hours}h`}
                    </PlanDesc>
                  </PlanMeta>
                  <StyledButton
                    type="button"
                    onClick={() => selectPlanFromPicker(plan)}
                    disabled={
                      portalLoading ||
                      checkoutLoadingSlug === plan.slug ||
                      checkoutLoadingSlug === '__default__'
                    }
                  >
                    {checkoutLoadingSlug === plan.slug
                      ? 'Starting…'
                      : planPickerMode === 'upgrade'
                        ? 'Upgrade'
                        : 'Select'}
                  </StyledButton>
                </PlanOption>
              ))}
            </PlanList>
            <ButtonRow>
              <SecondaryButton type="button" onClick={() => setShowPlanPicker(false)}>
                Close
              </SecondaryButton>
            </ButtonRow>
          </div>
        ) : null}

        {actionNotice ? (
          <NoticeText data-testid="billing-action-notice">{actionNotice}</NoticeText>
        ) : null}
        {actionError ? <ErrorText role="alert">{actionError}</ErrorText> : null}
      </GlassCard>

      <GlassCard data-testid="billing-history">
        <CardTitle>Billing history</CardTitle>
        {loading ? (
          <BodyText>Loading history…</BodyText>
        ) : listError ? (
          <ErrorText role="alert">{listError}</ErrorText>
        ) : historyRows.length === 0 ? (
          <BodyText>No invoices or payments yet.</BodyText>
        ) : (
          <div style={{ overflowX: 'auto' }}>
            <StyledTable>
              <thead>
                <tr>
                  <Th>Date</Th>
                  <Th>Provider</Th>
                  <Th>Description</Th>
                  <Th>Amount</Th>
                  <Th>Status</Th>
                  <Th>Invoice</Th>
                </tr>
              </thead>
              <tbody>
                {historyRows.map((row) => (
                  <tr key={row.key}>
                    <Td>{formatBillingDate(row.date)}</Td>
                    <Td>
                      <ProviderBadge>{row.provider}</ProviderBadge>
                    </Td>
                    <Td>{row.description}</Td>
                    <Td>{row.amount}</Td>
                    <Td>{row.status}</Td>
                    <Td>
                      {row.url ? (
                        <InvoiceLink href={row.url} target="_blank" rel="noreferrer">
                          View
                        </InvoiceLink>
                      ) : (
                        '—'
                      )}
                    </Td>
                  </tr>
                ))}
              </tbody>
            </StyledTable>
          </div>
        )}
      </GlassCard>

      {cancelConfirmOpen ? (
        <ModalBackdrop
          role="presentation"
          onClick={() => setCancelConfirmOpen(false)}
          data-testid="cancel-confirm-modal"
        >
          <ModalCard
            role="dialog"
            aria-modal="true"
            aria-labelledby="cancel-subscription-title"
            onClick={(event) => event.stopPropagation()}
          >
            <ModalTitle id="cancel-subscription-title">Cancel subscription?</ModalTitle>
            <BodyText>
              {native && (storeSub || showStoreManage) && !showStripeManage
                ? `You will cancel in ${storeLabel} subscription settings. Access typically continues until the end of the current billing period${periodEndLabel !== '—' ? ` (${periodEndLabel})` : ''}.`
                : `You will finish canceling in the Stripe customer portal. Access typically continues until the end of the current billing period${periodEndLabel !== '—' ? ` (${periodEndLabel})` : ''}.`}
            </BodyText>
            <ButtonRow>
              <DangerButton
                type="button"
                onClick={handleConfirmCancel}
                disabled={portalLoading}
              >
                {native && (storeSub || showStoreManage) && !showStripeManage
                  ? 'Got it'
                  : portalLoading
                    ? 'Opening…'
                    : 'Continue to cancel'}
              </DangerButton>
              <SecondaryButton
                type="button"
                onClick={() => setCancelConfirmOpen(false)}
                disabled={portalLoading}
              >
                Keep subscription
              </SecondaryButton>
            </ButtonRow>
          </ModalCard>
        </ModalBackdrop>
      ) : null}
    </>
  );
};

export default BillingSection;
