/* eslint-disable react/no-unstable-nested-components */
import { useLocaleContext } from '@arcblock/ux/lib/Locale/context';
import {
  formatAmount,
  Table,
  getPriceUintAmountByCurrency,
  formatNumber,
  formatTime,
  formatExchangeRate,
  getUsdAmountFromTokenUnits,
  formatUsdAmount,
  formatCreditForCheckout,
} from '@blocklet/payment-react';
import type { TInvoiceExpanded, TInvoiceItem } from '@blocklet/payment-types';
import { InfoOutlined } from '@mui/icons-material';
import { Box, Stack, Tooltip, Typography } from '@mui/material';
import { toBN, fromUnitToToken, fromTokenToUnit, BN } from '@ocap/util';
import { useSetState } from 'ahooks';

import { styled } from '@mui/system';
import { isEmpty } from 'lodash';
import { useNavigate } from 'react-router-dom';
import LineItemActions from '../subscription/items/actions';
import { UsageRecordDialog } from '../subscription/items/usage-records';
import { getInvoiceUsageReportStartEnd } from '../../libs/util';

type Props = {
  invoice: TInvoiceExpanded;
  simple?: boolean;
  emptyNodeText?: string;
  mode?: 'admin' | 'portal';
};

type InvoiceDetailItem = {
  id: string;
  product: string;
  credits?: {
    total: number;
    currency: string;
  };
  quantity: number;
  rawQuantity: number;
  price: string;
  referencePrice?: {
    amount: string;
    currency: string;
    decimals: number;
  } | null;
  amount: string;
  raw: TInvoiceItem;
  price_id: string;
  product_id: string;
};

type InvoiceSummaryItem = {
  key: string;
  value: string | React.ReactNode;
  color: string;
  usdReference?: string; // ≈ $X.XX format
  tooltip?: React.ReactNode;
  desc?: React.ReactNode;
};

export function getAppliedBalance(invoice: TInvoiceExpanded) {
  if (invoice.paymentMethod?.type === 'stripe') {
    const starting = toBN(invoice.starting_balance || '0');
    const ending = toBN(invoice.ending_balance || '0');
    return ending.sub(starting).toString();
  }

  if (
    invoice.starting_token_balance &&
    invoice.starting_token_balance[invoice.paymentCurrency.id] &&
    invoice.ending_token_balance &&
    invoice.ending_token_balance[invoice.paymentCurrency.id]
  ) {
    const starting = toBN(invoice.starting_token_balance[invoice.paymentCurrency.id] || '0');

    const ending = toBN(invoice.ending_token_balance[invoice.paymentCurrency.id] || '0');
    return ending.sub(starting).toString();
  }

  return '0';
}

export function getInvoiceRows(invoice: TInvoiceExpanded, t: (key: string) => string, locale?: string) {
  const detail: InvoiceDetailItem[] = invoice.lines.map((line) => {
    // Calculate actual payment unit price (in payment currency)
    // line.amount is in unit format (smallest unit)
    // line.quantity can be fractional (e.g., 0.5)
    let actualUnitPrice: string;
    if (line.quantity) {
      if (Number.isInteger(line.quantity)) {
        // If quantity is integer, use BN for precision
        actualUnitPrice = toBN(line.amount).div(toBN(line.quantity)).toString();
      } else {
        // If quantity is fractional, use floating point division
        const amountToken = fromUnitToToken(line.amount, invoice.paymentCurrency.decimal);
        const unitPriceToken = (Number(amountToken) / line.quantity).toFixed(invoice.paymentCurrency.decimal);
        const unitPriceResult = fromTokenToUnit(unitPriceToken, invoice.paymentCurrency.decimal);
        actualUnitPrice = typeof unitPriceResult === 'string' ? unitPriceResult : unitPriceResult.toString();
      }
    } else {
      actualUnitPrice = getPriceUintAmountByCurrency(line.price, invoice.paymentCurrency) || line.amount;
    }

    // Get quote info from metadata if available (for dynamic pricing)
    const quoteInfo = (line.metadata as any)?.quote;
    let referencePrice: { amount: string; currency: string; decimals: number } | null = null;

    if (quoteInfo?.base_amount && quoteInfo?.quantity) {
      // Calculate USD unit price from quote
      // base_amount is in USD with 8 decimals (token format, e.g., "10.50")
      // quantity can be fractional (e.g., 0.5)
      const USD_DECIMALS = 8;
      const baseAmount = Number(quoteInfo.base_amount);
      const quantity = Number(quoteInfo.quantity);

      if (quantity > 0 && !Number.isNaN(baseAmount)) {
        // Use floating point division for accuracy with fractional quantities
        const unitPriceToken = (baseAmount / quantity).toFixed(USD_DECIMALS);
        // Convert from token format to unit format (smallest unit)
        const unitPriceUnitResult = fromTokenToUnit(unitPriceToken, USD_DECIMALS);
        const unitPriceUnit =
          typeof unitPriceUnitResult === 'string' ? unitPriceUnitResult : unitPriceUnitResult.toString();

        referencePrice = {
          amount: unitPriceUnit,
          currency: quoteInfo.base_currency || 'USD',
          decimals: USD_DECIMALS,
        };
      }
    }

    const creditInfo = (line.price as any).credit;
    let credits: { total: number; currency: string } | undefined;

    if (creditInfo?.amount) {
      credits = {
        total: creditInfo.amount,
        currency: creditInfo.currency?.symbol || 'Credits',
      };
    }

    return {
      id: line.id,
      product: line.description.trim(),
      credits,
      quantity: line.quantity,
      rawQuantity: line.metadata?.quantity || 0,
      price: !line.proration
        ? `${formatAmount(actualUnitPrice, invoice.paymentCurrency.decimal)} ${invoice.paymentCurrency.symbol}`
        : '',
      referencePrice, // Add reference price (USD)
      amount: `${formatAmount(line.amount, invoice.paymentCurrency.decimal)} ${invoice.paymentCurrency.symbol}`,
      raw: line,
      price_id: line.price.id,
      product_id: line.price.product.id,
    };
  });

  const quoteLine = invoice.lines.find((line) => (line.metadata as any)?.quote?.exchange_rate);
  const quoteInfo = quoteLine ? (quoteLine.metadata as any).quote : null;

  // Calculate USD amount and exchange rate for subtotal
  let subtotalUsdAmount: string | null = null;
  let formattedRate: string | null = null;
  let rateLine: string | null = null;
  let exchangeRateTooltip: React.ReactNode = null;

  if (quoteInfo) {
    const providers = quoteInfo?.providers || [];
    const providerNames = providers.map((provider: any) => provider.provider_name).filter(Boolean);
    // Unified provider display format: "provider_name (n sources)" for multiple, specific name for single
    let providerDisplay: string;
    if (providers.length > 1) {
      providerDisplay = `${providerNames[0] || providers[0]?.provider_id || 'data'} (${providers.length} sources)`;
    } else if (providers.length === 1) {
      providerDisplay = providerNames[0] || providers[0]?.provider_id || '—';
    } else {
      providerDisplay = quoteInfo?.rate_provider_name || quoteInfo?.rate_provider_id;
    }
    const rateTimestamp = quoteInfo?.rate_timestamp_ms ? formatTime(quoteInfo.rate_timestamp_ms) : '—';

    // Calculate USD amount
    if (quoteInfo.exchange_rate && invoice.subtotal) {
      const calculatedUsd = getUsdAmountFromTokenUnits(
        new BN(invoice.subtotal),
        invoice.paymentCurrency.decimal,
        quoteInfo.exchange_rate
      );
      if (calculatedUsd) {
        subtotalUsdAmount = formatUsdAmount(calculatedUsd, locale);
      }
    }

    // Format exchange rate
    formattedRate = formatExchangeRate(quoteInfo.exchange_rate || null);
    if (formattedRate) {
      const currencyMap = {
        USD: '$',
        CNY: '¥',
      };
      const currencySymbol = currencyMap[quoteInfo.base_currency as keyof typeof currencyMap];
      rateLine = `1 ${invoice.paymentCurrency.symbol} ≈ ${currencySymbol ? `${currencySymbol}${formattedRate}` : `${formattedRate} ${quoteInfo.base_currency || 'USD'}`}`;
    }

    // Create tooltip content (same style as list.tsx)
    exchangeRateTooltip = (
      <Stack spacing={0.5} sx={{ p: 1 }}>
        <Stack direction="row" justifyContent="space-between" spacing={2}>
          <Typography variant="caption" sx={{ color: 'text.secondary' }}>
            {t('payment.customer.invoice.quote.providers')}:
          </Typography>
          <Typography variant="caption" sx={{ color: 'text.primary' }}>
            {providerDisplay || '—'}
          </Typography>
        </Stack>
        {rateLine && (
          <Stack direction="row" justifyContent="space-between" spacing={2}>
            <Typography variant="caption" sx={{ color: 'text.secondary' }}>
              {t('payment.customer.invoice.quote.exchangeRate')}:
            </Typography>
            <Typography variant="caption" sx={{ color: 'text.primary' }}>
              {rateLine}
            </Typography>
          </Stack>
        )}
        <Stack direction="row" justifyContent="space-between" spacing={2}>
          <Typography variant="caption" sx={{ color: 'text.secondary' }}>
            {t('payment.customer.invoice.quote.rateTimestamp')}:
          </Typography>
          <Typography variant="caption" sx={{ color: 'text.primary' }}>
            {rateTimestamp}
          </Typography>
        </Stack>
      </Stack>
    );
  }

  // Build subtotal value with USD reference
  const subtotalValue = (() => {
    if (!subtotalUsdAmount || !rateLine) {
      return null;
    }
    const rateText = (t as any)('payment.customer.invoice.quote.atPaymentRate', { rate: rateLine });
    return (
      <Stack alignItems="flex-end" sx={{ minWidth: '100px', textAlign: 'right' }}>
        <Tooltip
          title={exchangeRateTooltip}
          placement="top"
          arrow
          slotProps={{
            tooltip: {
              sx: {
                backgroundColor: 'background.paper',
                boxShadow: 1,
              },
            },
          }}>
          <Typography
            component="span"
            variant="caption"
            sx={{
              color: 'text.secondary',
              fontSize: '0.75rem',
              fontWeight: 400,
              lineHeight: 1.2,
              cursor: 'help',
            }}>
            ≈ ${subtotalUsdAmount} {rateText}
          </Typography>
        </Tooltip>
      </Stack>
    );
  })();

  const summary: InvoiceSummaryItem[] = [
    {
      key: 'common.subtotal',
      value: `${formatAmount(invoice.subtotal, invoice.paymentCurrency.decimal)} ${invoice.paymentCurrency.symbol}`,
      color: 'text.secondary',
      desc: subtotalValue,
    },
  ];

  // Add discount information from discountDetails
  if ((invoice as any).discountDetails && (invoice as any).discountDetails.length > 0) {
    (invoice as any).discountDetails.forEach((discount: any) => {
      if (discount.coupon) {
        let discountAmount = '0';

        // Calculate discount amount from total_discount_amounts
        if (invoice.total_discount_amounts && invoice.total_discount_amounts.length > 0) {
          const matchingDiscount = invoice.total_discount_amounts.find(
            (tda: any) => tda.discount === discount.id || tda.coupon === discount.coupon_id
          );
          if (matchingDiscount) {
            discountAmount = matchingDiscount.amount.toString();
          }
        }

        if (toBN(discountAmount).gt(toBN(0))) {
          const couponName = discount.coupon.name || t('common.coupon');
          const formattedDiscountAmount = formatAmount(discountAmount, invoice.paymentCurrency.decimal);

          // Format discount display following Stripe style: coupon_name (discount_type)
          let discountLabel = couponName;
          if (discount.coupon.percent_off) {
            const discountText = (t as any)('admin.coupon.couponTermsPercentage', {
              percent: discount.coupon.percent_off,
            });
            discountLabel = `${couponName} (${discountText})`;
          } else if (discount.coupon.amount_off) {
            const fixedAmount = formatAmount(discount.coupon.amount_off, invoice.paymentCurrency.decimal);
            const discountText = (t as any)('admin.coupon.couponTermsFixedAmount', {
              amount: fixedAmount,
              symbol: invoice.paymentCurrency.symbol,
            });
            discountLabel = `${couponName} (${discountText})`;
          }

          summary.push({
            key: discountLabel,
            value: `-${formattedDiscountAmount} ${invoice.paymentCurrency.symbol}`,
            color: 'text.secondary',
          });
        }
      }
    });
  }

  summary.push({
    key: 'common.total',
    value: `${formatAmount(invoice.total, invoice.paymentCurrency.decimal)} ${invoice.paymentCurrency.symbol}`,
    color: 'text.secondary',
  });
  if (invoice.amount_paid !== '0') {
    summary.push({
      key: 'payment.customer.invoice.amountPaid',
      value: `${formatAmount(invoice.amount_paid, invoice.paymentCurrency.decimal)} ${invoice.paymentCurrency.symbol}`,
      color: 'text.secondary',
    });
  }

  const appliedBalance = getAppliedBalance(invoice);
  if (appliedBalance !== '0') {
    summary.push({
      key: 'payment.customer.invoice.amountApplied',
      value: `${formatAmount(appliedBalance, invoice.paymentCurrency.decimal)} ${invoice.paymentCurrency.symbol}`,
      color: 'text.secondary',
    });
  }
  summary.push({
    key: 'payment.customer.invoice.amountDue',
    value: `${formatAmount(invoice.amount_remaining, invoice.paymentCurrency.decimal)} ${invoice.paymentCurrency.symbol}`,
    color: invoice.amount_remaining !== '0' ? 'text.primary' : 'text.secondary',
  });

  return {
    detail,
    summary,
  };
}

export default function InvoiceTable({ invoice, simple = false, emptyNodeText = '', mode = 'portal' }: Props) {
  const { t, locale } = useLocaleContext();
  const isAdmin = mode === 'admin';
  const navigate = useNavigate();
  const { detail, summary } = getInvoiceRows(invoice, t, locale);
  const [state, setState] = useSetState({
    subscriptionId: '',
    subscriptionItemId: '',
  });

  const usageReportRange = getInvoiceUsageReportStartEnd(invoice, true);

  const onOpenUsageRecords = (line: InvoiceDetailItem) => {
    if (line.rawQuantity && line.raw.subscription_id && line.raw.subscription_item_id) {
      setState({
        subscriptionId: line.raw.subscription_id,
        subscriptionItemId: line.raw.subscription_item_id,
      });
    }
  };

  const onCloseUsageRecords = () => {
    setState({
      subscriptionId: '',
      subscriptionItemId: '',
    });
  };

  const columns = [
    {
      label: t('admin.subscription.product'),
      name: 'product',
      options: {
        customBodyRenderLite: (_: string, index: number) => {
          const item = detail[index] as InvoiceDetailItem;

          return (
            <Box>
              <Typography
                component="div"
                sx={{
                  textAlign: {
                    xs: 'right',
                    md: 'left',
                  },
                }}>
                {item.product}
              </Typography>
              {item.credits && (
                <Typography
                  component="div"
                  variant="caption"
                  sx={{
                    color: 'text.secondary',
                    mt: 0.5,
                    wordBreak: 'break-word',
                    textAlign: {
                      xs: 'right',
                      md: 'left',
                    },
                  }}>
                  {t('customer.invoice.creditsInfo', {
                    amount: formatCreditForCheckout(formatNumber(item.credits.total), item.credits.currency, locale),
                  })}
                </Typography>
              )}
            </Box>
          );
        },
      },
    },
    {
      label: t('common.quantity'),
      name: 'quantity',
      width: 200,
      align: 'right',
      options: {
        filter: true,
        customBodyRenderLite: (_: string, index: number) => {
          const item = detail[index] as InvoiceDetailItem;
          return (
            <Stack
              direction="row"
              spacing={0.5}
              onClick={() => onOpenUsageRecords(item)}
              sx={{
                alignItems: 'center',
                cursor: 'pointer',

                justifyContent: {
                  xs: 'flex-start',
                  md: 'flex-end',
                },
              }}>
              <Typography component="span">{item.quantity}</Typography>
              {!!item.rawQuantity && (
                <Tooltip
                  title={t('payment.customer.invoice.rawQuantity', { quantity: item.rawQuantity })}
                  placement="top">
                  <InfoOutlined fontSize="small" sx={{ color: 'text.secondary', cursor: 'pointer' }} />
                </Tooltip>
              )}
            </Stack>
          );
        },
      },
    },
    {
      label: t('payment.customer.invoice.unitPrice'),
      name: 'price',
      width: 200,
      align: 'right',
      options: {
        customBodyRenderLite: (_: string, index: number) => {
          const item = detail[index] as InvoiceDetailItem;
          return (
            <Typography
              component="div"
              variant="body2"
              sx={{
                textAlign: {
                  xs: 'left',
                  md: 'right',
                },
              }}>
              {item.price}
            </Typography>
          );
        },
      },
    },

    {
      label: t('common.amount'),
      name: 'amount',
      width: 200,
      align: 'right',
      options: {
        customBodyRenderLite: (_: string, index: number) => {
          const item = detail[index] as InvoiceDetailItem;
          return <Typography component="span">{invoice.status === 'void' ? '0' : item.amount}</Typography>;
        },
      },
    },

    ...(isAdmin
      ? [
          {
            label: t('admin.taxRate.label'),
            name: 'tax_rate',
            width: 100,
            align: 'right',
            options: {
              customBodyRenderLite: (_: string, index: number) => {
                const item = detail[index] as InvoiceDetailItem;
                const taxRate = (item.raw as any).tax_rate;
                if (!taxRate) {
                  return (
                    <Typography component="span" sx={{ color: 'text.secondary' }}>
                      —
                    </Typography>
                  );
                }
                return (
                  <Tooltip
                    title={`${taxRate.display_name || taxRate.id} (${taxRate.percentage}%)`}
                    arrow
                    placement="top">
                    <Typography
                      component="span"
                      sx={{
                        color: 'text.link',
                        fontWeight: 500,
                        cursor: 'default',
                      }}
                      onClick={() => navigate(`/admin/tax/${taxRate.id}`)}>
                      {taxRate.percentage}%
                    </Typography>
                  </Tooltip>
                );
              },
            },
          },
        ]
      : []),
    {
      label: t('common.discount'),
      name: 'discount',
      width: 200,
      align: 'right',
      options: {
        customBodyRenderLite: (_: string, index: number) => {
          const item = detail[index] as InvoiceDetailItem;
          // Calculate discount amount for this line item
          let itemDiscountAmount = toBN(0);
          if (item.raw.discount_amounts && item.raw.discount_amounts.length > 0) {
            item.raw.discount_amounts.forEach((discount: any) => {
              if (discount.amount) {
                itemDiscountAmount = itemDiscountAmount.add(toBN(discount.amount));
              }
            });
          }

          return (
            <Typography component="span" sx={{ color: 'text.secondary' }}>
              {itemDiscountAmount.gt(toBN(0))
                ? `-${formatAmount(itemDiscountAmount.toString(), invoice.paymentCurrency.decimal)} ${invoice.paymentCurrency.symbol}`
                : '-'}
            </Typography>
          );
        },
      },
    },
    ...(simple
      ? []
      : [
          {
            label: t('common.actions'),
            name: '',
            width: 80,
            options: {
              customBodyRenderLite: (_: string, index: number) => {
                const item = detail[index] as InvoiceDetailItem;
                return <LineItemActions data={item.raw as any} mode={mode} />;
              },
            },
          },
        ]),
  ];

  return (
    <Root>
      <Table
        data={detail}
        columns={columns}
        loading={false}
        footer={false}
        toolbar={false}
        components={{
          TableToolbar: () => null,
          TableFooter: () => null,
        }}
        options={{
          count: detail.length,
          page: 0,
          rowsPerPage: 100,
          // responsive: 'simple',
        }}
        dire
        locale={locale}
        mobileTDFlexDirection="row"
        emptyNodeText={emptyNodeText || t('payment.customer.invoice.emptyList')}
      />
      {!isEmpty(detail) && invoice.status !== 'void' && (
        <Box
          className="invoice-summary"
          sx={{
            display: 'flex',
            flexDirection: 'column',
            alignItems: 'flex-end',
            float: 'right',
            pr: 2,
            mt: {
              xs: 1,
              md: 1,
            },
            width: '100%',
            minWidth: {
              md: '280px',
            },
          }}>
          {summary.map((line, index) => {
            const isTotal = line.key === 'common.total';
            const showDivider = isTotal && index > 0;

            return (
              <>
                <Stack
                  key={line.key}
                  direction="row"
                  sx={{
                    justifyContent: 'flex-end',
                    width: '100%',
                    py: 0.5,
                    gap: 2,

                    ...(showDivider && {
                      borderTop: '1px solid',
                      borderTopColor: 'divider',
                      pt: 1,
                      mt: 0.5,
                    }),
                  }}>
                  <Typography
                    variant="body2"
                    sx={{
                      color: 'text.primary',
                      fontWeight: isTotal ? 500 : 400,
                    }}>
                    {line.key.startsWith('common.') || line.key.startsWith('payment.') ? t(line.key) : line.key}
                  </Typography>
                  <Typography
                    variant="body2"
                    sx={{
                      color: 'text.primary',
                      fontWeight: isTotal ? 500 : 400,
                      minWidth: '100px',
                      textAlign: 'right',
                    }}>
                    {line.value}
                  </Typography>
                </Stack>
                {(() => {
                  if (line.tooltip && line.desc) {
                    return (
                      <Tooltip title={line.tooltip} placement="top" arrow>
                        <Box component="span">{line.desc}</Box>
                      </Tooltip>
                    );
                  }
                  return line.desc;
                })()}
              </>
            );
          })}
        </Box>
      )}
      {state.subscriptionId && state.subscriptionItemId && (
        <UsageRecordDialog
          subscriptionId={state.subscriptionId}
          id={state.subscriptionItemId}
          onConfirm={onCloseUsageRecords}
          start={usageReportRange.start}
          end={usageReportRange.end}
          title={t('admin.subscription.usage.title')}
          disableAddUsageQuantity
        />
      )}
    </Root>
  );
}

const Root = styled(Box)`
  @media (max-width: ${({ theme }) => theme.breakpoints.values.md}px) {
    .MuiTable-root > .MuiTableBody-root > .MuiTableRow-root > td.MuiTableCell-root {
      > div {
        width: fit-content;
        flex: inherit;
        font-size: 14px;
      }
    }
  }
`;
