/* eslint-disable react/no-unstable-nested-components */
import { useLocaleContext } from '@arcblock/ux/lib/Locale/context';
import {
  Status,
  Table,
  TxLink,
  api,
  formatBNStr,
  formatTime,
  formatToDate,
  getPaymentIntentStatusColor,
} from '@blocklet/payment-react';
import type { Paginated, TRefundExpanded } from '@blocklet/payment-types';
import { Box, Button, CircularProgress, Stack, Typography } from '@mui/material';
import { styled } from '@mui/system';
import { useInfiniteScroll, useRequest } from 'ahooks';
import { capitalize, toLower } from 'lodash';
import { memo, useState } from 'react';

const groupByDate = (items: TRefundExpanded[]) => {
  const grouped: { [key: string]: TRefundExpanded[] } = {};
  items.forEach((item) => {
    const date = new Date(item.created_at).toLocaleDateString();
    if (!grouped[date]) {
      grouped[date] = [];
    }
    grouped[date]?.push(item);
  });
  return grouped;
};

const fetchData = (params: Record<string, any> = {}): Promise<Paginated<TRefundExpanded>> => {
  const search = new URLSearchParams();
  Object.keys(params).forEach((key) => {
    search.set(key, String(params[key]));
  });
  return api.get(`/api/refunds?${search.toString()}`).then((res: any) => res.data);
};

type Props = {
  invoice_id: string;
};

const pageSize = 10;

const RefundTable = memo(({ invoice_id }: Props) => {
  const listKey = 'invoice-table';
  const { t, locale } = useLocaleContext();

  const [search, setSearch] = useState<{ pageSize: number; page: number }>({
    pageSize: pageSize || 10,
    page: 1,
  });
  const { loading, data = { list: [], count: 0 } } = useRequest(
    () =>
      fetchData({
        ...search,
        invoice_id,
      }),
    {
      refreshDeps: [search],
    }
  );

  const columns = [
    {
      label: t('common.amount'),
      name: 'id',
      width: 80,
      align: 'right',
      options: {
        customBodyRenderLite: (_: string, index: number) => {
          const item = data.list[index] as TRefundExpanded;
          return (
            <Typography
              component="strong"
              sx={{
                fontWeight: 600,
              }}>
              {formatBNStr(item?.amount, item?.paymentCurrency.decimal)}
              {item?.paymentCurrency.symbol}
            </Typography>
          );
        },
      },
    },
    {
      label: t('common.status'),
      name: 'status',
      width: 100,
      options: {
        filter: true,
        customBodyRenderLite: (_: string, index: number) => {
          const item = data.list[index] as TRefundExpanded;
          return <Status label={item.status} color={getPaymentIntentStatusColor(item.status)} />;
        },
      },
    },
    {
      label: t('common.type'),
      name: 'type',
      width: 80,
      options: {
        filter: true,
        customBodyRenderLite: (_: string, index: number) => {
          const item = data.list[index] as TRefundExpanded;
          return <Status label={t(`refund.type.${item.type}`)} />;
        },
      },
    },
    {
      label: t('common.description'),
      name: 'description',
      options: {
        customBodyRenderLite: (_: string, index: number) => {
          const item = data.list[index] as TRefundExpanded;
          return item.description ? capitalize(toLower(item.description.replace(/_/g, ' '))) : item.id;
        },
      },
    },
    {
      label: t('common.createdAt'),
      name: 'created_at',
      options: {
        sort: true,
        customBodyRenderLite: (_: string, index: number) => {
          const item = data.list[index] as TRefundExpanded;
          return formatTime(item.created_at);
        },
      },
    },
    {
      label: t('common.updatedAt'),
      name: 'updated_at',
      options: {
        sort: true,
        customBodyRenderLite: (_: string, index: number) => {
          const item = data.list[index] as TRefundExpanded;
          return formatTime(item.updated_at);
        },
      },
    },
    {
      label: t('common.txHash'),
      name: '',
      options: {
        customBodyRenderLite: (_: string, index: number) => {
          const item = data.list[index] as TRefundExpanded;
          const paymentDetails = item.payment_details as Record<string, { tx_hash?: string }>;
          const txHash = ['arcblock', 'ethereum', 'base'].map((key) => !!paymentDetails?.[key]?.tx_hash).find(Boolean);
          return txHash ? (
            <Box
              sx={{
                '.MuiTypography-root': {
                  color: 'text.link',
                },
              }}>
              <TxLink details={paymentDetails} method={item.paymentMethod} mode="customer" />
            </Box>
          ) : (
            t('common.none')
          );
        },
      },
    },
  ];

  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>
      <Table
        hasRowLink
        durable={`__${listKey}__`}
        durableKeys={['page', 'rowsPerPage', 'searchText']}
        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}
        locale={locale}
        mobileTDFlexDirection="row"
        emptyNodeText={t('payment.customer.refund.emptyList')}
      />
    </TableRoot>
  );
});

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

const RefundList = memo(({ invoice_id }: Props) => {
  const { t } = useLocaleContext();

  const { data, loadMore, loadingMore, loading } = useInfiniteScroll<Paginated<TRefundExpanded>>(
    (d) => {
      const page = d ? Math.ceil(d.list.length / pageSize) + 1 : 1;
      return fetchData({ page, pageSize, invoice_id });
    },
    {
      reloadDeps: [invoice_id],
    }
  );

  if (loading || !data) {
    return <CircularProgress />;
  }

  if (data && data.list.length === 0) {
    return (
      <Typography
        sx={{
          color: 'text.secondary',
        }}>
        {t('payment.customer.refund.empty')}
      </Typography>
    );
  }

  const hasMore = data && data.list.length < data.count;

  const grouped = groupByDate(data.list);

  return (
    <Stack
      direction="column"
      sx={{
        gap: 1,
        mt: 1,
      }}>
      {Object.entries(grouped).map(([date, payments]) => (
        <Box key={date}>
          <Typography sx={{ fontWeight: 'bold', color: 'text.secondary', mt: 2, mb: 1 }}>{date}</Typography>
          {payments.map((item: TRefundExpanded) => {
            return (
              <Stack
                key={item.id}
                direction={{
                  xs: 'column',
                  sm: 'row',
                }}
                sx={{
                  gap: {
                    xs: 0.5,
                    sm: 1.5,
                    md: 3,
                  },

                  flexWrap: 'nowrap',
                  my: 1,
                }}>
                <Box
                  sx={{
                    flex: 3,
                  }}>
                  <Typography>{formatToDate(item.created_at)}</Typography>
                </Box>
                <Box
                  sx={{
                    flex: 2,
                  }}>
                  <Typography
                    sx={{
                      textAlign: 'right',
                    }}>
                    {formatBNStr(item.amount, item.paymentCurrency.decimal)}&nbsp;
                    {item.paymentCurrency.symbol}
                  </Typography>
                </Box>
                <Box
                  sx={{
                    flex: 3,
                  }}>
                  <Status label={item.status} color={getPaymentIntentStatusColor(item.status)} />
                </Box>
                <Box
                  sx={{
                    flex: 3,
                  }}>
                  <Typography>
                    {item.description ? capitalize(toLower(item.description.replace(/_/g, ' '))) : '-'}
                  </Typography>
                </Box>
                <Box
                  sx={{
                    flex: 3,
                    minWidth: '220px',
                  }}>
                  {(item.payment_details?.arcblock?.tx_hash ||
                    item.payment_details?.ethereum?.tx_hash ||
                    item.payment_details?.base?.tx_hash) && (
                    <TxLink details={item.payment_details} method={item.paymentMethod} mode="customer" />
                  )}
                </Box>
              </Stack>
            );
          })}
        </Box>
      ))}
      <Box>
        {hasMore && (
          <Button variant="text" type="button" color="inherit" onClick={loadMore} disabled={loadingMore}>
            {loadingMore
              ? t('common.loadingMore', { resource: t('payment.customer.payments') })
              : t('common.loadMore', { resource: t('payment.customer.payments') })}
          </Button>
        )}
        {!hasMore && data.count > pageSize && (
          <Typography
            sx={{
              color: 'text.secondary',
            }}>
            {t('common.noMore', { resource: t('payment.customer.payments') })}
          </Typography>
        )}
      </Box>
    </Stack>
  );
});

export default function CustomerRefundList({ type = 'list', ...restProps }: Props & { type?: 'table' | 'list' }) {
  if (type === 'table') {
    return <RefundTable {...restProps} />;
  }
  return <RefundList {...restProps} />;
}
