/* eslint-disable @typescript-eslint/indent */
/* eslint-disable react/require-default-props */
/* eslint-disable react/no-unused-prop-types */
/* eslint-disable @typescript-eslint/naming-convention */
/* eslint-disable no-nested-ternary */
/* eslint-disable react/no-unstable-nested-components */
import { useLocaleContext } from '@arcblock/ux/lib/Locale/context';
import type { Paginated, TCreditTransactionExpanded } from '@blocklet/payment-types';
import { Box, Typography, Grid, Stack, Link, Button } from '@mui/material';
import { useRequest } from 'ahooks';
// eslint-disable-next-line import/no-extraneous-dependencies
import { useNavigate } from 'react-router-dom';
import React, { useEffect, useRef, useState } from 'react';
import { styled } from '@mui/system';
import { joinURL } from 'ufo';
import DateRangePicker, { type DateRangeValue } from '../../components/date-range-picker';
// eslint-disable-next-line import/no-extraneous-dependencies

import { formatToDate, getPrefix, formatCreditAmount, formatBNStr } from '../../libs/util';
import { usePaymentContext } from '../../contexts/payment';
import api from '../../libs/api';
import Table from '../../components/table';
import { createLink, handleNavigation } from '../../libs/navigation';

type Result = Paginated<TCreditTransactionExpanded>;

const fetchData = (params: Record<string, any> = {}): Promise<Result> => {
  const search = new URLSearchParams();
  Object.keys(params).forEach((key) => {
    if (params[key]) {
      search.set(key, String(params[key]));
    }
  });

  return api.get(`/api/credit-transactions?${search.toString()}`).then((res: any) => res.data);
};

type Props = {
  customer_id?: string;
  subscription_id?: string;
  credit_grant_id?: string;
  pageSize?: number;
  onTableDataChange?: Function;
  showAdminColumns?: boolean;
  showTimeFilter?: boolean;
  includeGrants?: boolean; // Enable unified cash flow view
  source?: string;
  mode?: 'dashboard' | 'portal';
};

const getGrantDetailLink = (grantId: string, inDashboard: boolean) => {
  let path = `/customer/credit-grant/${grantId}`;
  if (inDashboard) {
    path = `/admin/customers/${grantId}`;
  }

  return {
    link: createLink(path),
    connect: false,
  };
};

const getInvoiceDetailLink = (invoiceId: string, inDashboard: boolean) => {
  let path = `/customer/invoice/${invoiceId}`;
  if (inDashboard) {
    path = `/admin/billing/${invoiceId}`;
  }

  return {
    link: createLink(path),
    connect: false,
  };
};

const getSubscriptionDetailLink = (subscriptionId: string, inDashboard: boolean) => {
  let path = `/customer/subscription/${subscriptionId}`;
  if (inDashboard) {
    path = `/admin/billing/${subscriptionId}`;
  }

  return {
    link: createLink(path),
    connect: false,
  };
};

const getCreditTransactionDetailLink = (transactionId: string) => {
  const path = `/customer/credit-transaction/${transactionId}`;

  return {
    link: createLink(path),
    connect: false,
  };
};

const getMeterEventDetailLink = (meterEventId: string) => {
  // Meter event detail page is only available in admin dashboard
  const path = `/admin/billing/${meterEventId}`;

  return {
    link: createLink(path),
    connect: false,
  };
};

const getSubscriptionId = (item: any) =>
  item.metadata?.subscription_id || item.subscription_id || item.invoice?.subscription_id;

const getInvoiceId = (item: any) => item.metadata?.invoice_id || item.invoice?.id;
const getMeterEventId = (item: any) => item.source || item.metadata?.meter_event_id;

// Extract credit activity classification logic for table columns reuse
const getCreditActivityFlags = (item: any) => {
  const isGrant = item.activity_type === 'grant';
  const isScheduled = isGrant && item.metadata?.delivery_mode === 'schedule';
  const isDepleted = isGrant && item.status === 'depleted';
  const isExpired = isGrant && (item.status === 'expired' || item.status === 'voided');
  const isInactive = isDepleted || isExpired;

  return { isGrant, isScheduled, isDepleted, isExpired, isInactive };
};

const getTransactionDetailLink = (item: any, inDashboard: boolean) => {
  if (item.activity_type === 'grant') {
    const invoiceId = getInvoiceId(item);
    if (invoiceId) {
      return getInvoiceDetailLink(invoiceId, inDashboard);
    }

    return getGrantDetailLink(item.id, inDashboard);
  }

  if (!inDashboard) {
    return getCreditTransactionDetailLink(item.id);
  }

  const meterEventId = getMeterEventId(item);
  if (!meterEventId) {
    return null;
  }

  return getMeterEventDetailLink(meterEventId);
};

const getTransactionDescription = (item: any, t: Function) => {
  const { isGrant, isScheduled, isInactive } = getCreditActivityFlags(item);
  const isPaid = isGrant && item.category === 'paid' && (!isScheduled || item.metadata?.schedule_seq === 1);

  if (!isGrant) {
    const secondLine = item.metadata?.is_repayment ? t('common.creditActivity.repayment') : item.description || '';
    return {
      isGrant,
      isInactive,
      activityType: t('common.creditActivity.consumption'),
      secondLine,
    };
  }

  if (isPaid) {
    let secondLine = item.description || '';
    if (item.invoice?.total && item.invoice?.paymentCurrency) {
      const invoiceCurrency = item.invoice.paymentCurrency;
      const paidAmount = formatCreditAmount(
        formatBNStr(item.invoice.total, invoiceCurrency.decimal || 0),
        invoiceCurrency.symbol || ''
      );
      secondLine = t('common.creditActivity.paidAmount', { amount: paidAmount });
    }

    return {
      isGrant,
      isInactive,
      activityType: t('common.creditActivity.paidGrant'),
      secondLine,
    };
  }

  if (isScheduled) {
    return {
      isGrant,
      isInactive,
      activityType: t('common.creditActivity.resetGrant'),
      secondLine: item.description || '',
    };
  }

  return {
    isGrant,
    isInactive,
    activityType: t('common.creditActivity.promotionalGrant'),
    secondLine: item.description || '',
  };
};

const TransactionsTable = React.memo((props: Props) => {
  const {
    pageSize,
    customer_id,
    subscription_id,
    credit_grant_id,
    onTableDataChange,
    showAdminColumns = false,
    showTimeFilter = false,
    includeGrants = false,
    source,
    mode = 'portal',
  } = props;
  const listKey = 'credit-transactions-table';
  const { t, locale } = useLocaleContext();
  const { session } = usePaymentContext();
  const isAdmin = ['owner', 'admin'].includes(session?.user?.role || '');
  const isDashboard = isAdmin && mode === 'dashboard';
  const navigate = useNavigate();

  // 如果没有传入 customer_id，使用当前登录用户的 DID
  const effectiveCustomerId = customer_id || session?.user?.did;

  const [search, setSearch] = useState<{
    pageSize: number;
    page: number;
    start?: number;
    end?: number;
  }>({
    pageSize: pageSize || 10,
    page: 1,
  });

  const [filters, setFilters] = useState<DateRangeValue>({
    start: undefined,
    end: undefined,
  });

  const handleDateRangeChange = (newValue: DateRangeValue) => {
    setFilters(newValue);
    setSearch((prev) => ({
      ...prev,
      page: 1,
      start: newValue.start || undefined,
      end: newValue.end || undefined,
    }));
  };

  const { loading, data = { list: [], count: 0 } } = useRequest(
    () =>
      fetchData({
        ...search,
        customer_id: effectiveCustomerId,
        subscription_id,
        credit_grant_id,
        source,
        include_grants: includeGrants,
      }),
    {
      refreshDeps: [search, effectiveCustomerId, subscription_id, credit_grant_id, source, includeGrants],
    }
  );

  // 初始化时应用默认日期筛选
  useEffect(() => {
    if (showTimeFilter && !search.start && !search.end) {
      setSearch((prev) => ({
        ...prev,
        page: 1,
        start: filters.start || undefined,
        end: filters.end || undefined,
      }));
    }
  }, [showTimeFilter, search.start, search.end, filters.start, filters.end]);

  const prevData = useRef(data);

  useEffect(() => {
    if (onTableDataChange) {
      onTableDataChange(data, prevData.current);
      prevData.current = data;
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [data]);

  const handleTransactionClick = (e: React.MouseEvent, item: any) => {
    const detail = getTransactionDetailLink(item, isDashboard);
    if (!detail) {
      return;
    }

    handleNavigation(e, detail.link, navigate, { target: detail.link.external ? '_blank' : '_self' });
  };
  const openSubscription = (e: React.MouseEvent, subscriptionId: string) => {
    e.preventDefault();
    const link = getSubscriptionDetailLink(subscriptionId, isDashboard);
    handleNavigation(e, link.link, navigate);
  };

  const openInvoice = (e: React.MouseEvent, invoiceId: string) => {
    e.preventDefault();
    const link = getInvoiceDetailLink(invoiceId, isDashboard);
    handleNavigation(e, link.link, navigate);
  };

  const renderActionButton = (label: string, onClick: (e: React.MouseEvent) => void) => (
    <Button variant="text" size="small" color="primary" sx={{ whiteSpace: 'nowrap' }} onClick={onClick}>
      {label}
    </Button>
  );

  const columns = [
    {
      label: t('common.date'),
      name: 'created_at',
      options: {
        setCellProps: () => ({ style: { width: '25%' } }),
        customBodyRenderLite: (_: string, index: number) => {
          const item = data?.list[index] as any;
          return (
            <Box onClick={(e) => handleTransactionClick(e, item)}>
              <Typography variant="body2" sx={{ fontSize: '0.875rem' }}>
                {formatToDate(item.created_at, locale, 'YYYY-MM-DD HH:mm')}
              </Typography>
            </Box>
          );
        },
      },
    },
    {
      label: t('common.description'),
      name: 'description',
      options: {
        setCellProps: () => ({ style: { width: '25%' } }),
        customBodyRenderLite: (_: string, index: number) => {
          const item = data?.list[index] as any;
          const { activityType, secondLine, isInactive, isGrant } = getTransactionDescription(item, t);

          return (
            <Box onClick={(e) => handleTransactionClick(e, item)} sx={{ cursor: 'pointer' }}>
              <Stack direction="column" spacing={0.25}>
                <Typography
                  variant="body2"
                  sx={{
                    color: isInactive ? 'text.secondary' : isGrant ? 'success.main' : 'error.main',
                  }}>
                  {activityType}
                </Typography>
                {secondLine && (
                  <Typography variant="caption" sx={{ color: 'text.secondary' }}>
                    {secondLine}
                  </Typography>
                )}
              </Stack>
            </Box>
          );
        },
      },
    },
    {
      label: t('common.amount'),
      name: 'credit_amount',
      align: 'right',
      options: {
        setCellProps: () => ({ style: { width: '20%' } }),
        customHeadLabelRender: () => <Box sx={{ pr: 5 }}>{t('common.amount')}</Box>,
        customBodyRenderLite: (_: string, index: number) => {
          const item = data?.list[index] as any;
          const { isGrant, isDepleted, isExpired, isInactive } = getCreditActivityFlags(item);
          const amount = isGrant ? item.amount : item.credit_amount;
          const currency = item.paymentCurrency || item.currency;
          const unit = !isGrant && item.meter?.unit ? item.meter.unit : currency?.symbol;
          const displayAmount = formatCreditAmount(formatBNStr(amount, currency?.decimal || 0), unit);

          if (!includeGrants) {
            return (
              <Box onClick={(e) => handleTransactionClick(e, item)} sx={{ pr: 5 }}>
                <Typography>{displayAmount}</Typography>
              </Box>
            );
          }

          return (
            <Box onClick={(e) => handleTransactionClick(e, item)} sx={{ pr: 5 }}>
              <Stack direction="column" spacing={0.25} alignItems="flex-end">
                <Typography
                  sx={{
                    fontWeight: 500,
                    color: isInactive ? 'text.secondary' : isGrant ? 'success.main' : 'error.main',
                    whiteSpace: 'nowrap',
                  }}>
                  {isGrant ? '+' : '-'} {displayAmount}
                </Typography>
                {isDepleted ? (
                  <Typography variant="caption" sx={{ color: 'text.secondary' }}>
                    {t('common.consumed')}
                  </Typography>
                ) : isExpired ? (
                  <Typography variant="caption" sx={{ color: 'text.secondary' }}>
                    {t('common.expired')}
                  </Typography>
                ) : null}
              </Stack>
            </Box>
          );
        },
      },
    },
    ...(showAdminColumns && isAdmin
      ? [
          {
            label: t('common.meterEvent'),
            name: 'meter_event',
            options: {
              customBodyRenderLite: (_: string, index: number) => {
                const transaction = data?.list[index] as TCreditTransactionExpanded;
                if (!transaction.meter) {
                  return <Typography variant="body2">-</Typography>;
                }
                return (
                  <Link href={joinURL(getPrefix(), `/admin/billing/${transaction.meter.id}`)}>
                    <Typography variant="body2" sx={{ color: 'text.link' }}>
                      {transaction.meter.event_name}
                    </Typography>
                  </Link>
                );
              },
            },
          },
        ]
      : []),
    {
      label: t('common.actions'),
      name: 'actions',
      options: {
        setCellProps: () => ({ style: { width: '25%' } }),
        customBodyRenderLite: (_: string, index: number) => {
          const item = data?.list[index] as any;
          const { isGrant, isScheduled } = getCreditActivityFlags(item);
          const isPaid = isGrant && item.category === 'paid' && !isScheduled;
          const subscriptionId = getSubscriptionId(item);
          const invoiceId = isGrant ? getInvoiceId(item) : null;
          const shouldShowSubscription = Boolean(subscriptionId) && (!isGrant || isScheduled || isPaid);

          return (
            <Box sx={{ display: 'flex', gap: 1, alignItems: 'center', flexWrap: 'nowrap' }}>
              {shouldShowSubscription && subscriptionId
                ? renderActionButton(t('common.viewSubscription'), (e) => openSubscription(e, subscriptionId))
                : null}
              {isPaid && invoiceId
                ? renderActionButton(t('common.viewInvoice'), (e) => openInvoice(e, invoiceId))
                : null}
            </Box>
          );
        },
      },
    },
  ].filter(Boolean);

  const onTableChange = ({ page, rowsPerPage }: any) => {
    if (search.pageSize !== rowsPerPage) {
      setSearch((x) => ({ ...x, pageSize: rowsPerPage, page: 1 }));
    } else if (search.page !== page + 1) {
      setSearch((x) => ({ ...x, page: page + 1 }));
    }
  };

  return (
    <TableRoot>
      {showTimeFilter && (
        <Box sx={{ my: 2 }}>
          <Box sx={{ mt: 2 }}>
            <Grid
              container
              spacing={2}
              sx={{
                alignItems: 'center',
              }}>
              <Grid
                size={{
                  xs: 12,
                  sm: 6,
                  md: 4,
                }}>
                <DateRangePicker value={filters} onChange={handleDateRangeChange} size="small" fullWidth />
              </Grid>
            </Grid>
          </Box>
        </Box>
      )}
      <Table
        hasRowLink
        durable={`__${listKey}__`}
        durableKeys={['page', 'rowsPerPage']}
        data={data.list}
        columns={columns}
        options={{
          count: data.count,
          page: search.page - 1,
          rowsPerPage: search.pageSize,
        }}
        loading={loading}
        onChange={onTableChange}
        toolbar={false}
        sx={{ mt: 2 }}
        showMobile={false}
        mobileTDFlexDirection="row"
        emptyNodeText={t('admin.creditTransactions.noTransactions')}
      />
    </TableRoot>
  );
});

const TableRoot = 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;
      }
    }
    .invoice-summary {
      padding-right: 20px;
    }
  }
`;
export default function CreditTransactionsList(rawProps: Props) {
  const props = Object.assign(
    {
      customer_id: '',
      subscription_id: '',
      credit_grant_id: '',
      source: '',
      pageSize: 10,
      onTableDataChange: () => {},
      showAdminColumns: false,
      showTimeFilter: false,
      includeGrants: false,
      mode: 'portal',
    },
    rawProps
  );
  return <TransactionsTable {...props} />;
}
