/* eslint-disable react/no-unstable-nested-components */
import { useLocaleContext } from '@arcblock/ux/lib/Locale/context';
import {
  Status,
  api,
  formatBNStr,
  formatTime,
  getPaymentIntentStatusColor,
  Table,
  useDefaultPageSize,
} from '@blocklet/payment-react';
import type { TRefundExpanded } from '@blocklet/payment-types';
import { Avatar, CircularProgress, Typography } from '@mui/material';
import { useEffect, useState } from 'react';
import { Link, useSearchParams } from 'react-router-dom';

import { capitalize, toLower } from 'lodash';
import CustomerLink from '../customer/link';
import FilterToolbar from '../filter-toolbar';
import RefundActions from './actions';
import { useCacheState } from '../../hooks/cache-state';

const fetchData = (params: Record<string, any> = {}): Promise<{ list: TRefundExpanded[]; count: number }> => {
  const search = new URLSearchParams();
  Object.keys(params).forEach((key) => {
    let v = params[key];
    if (key === 'q') {
      v = Object.entries(v)
        .map((x) => x.join(':'))
        .join(' ');
    }
    search.set(key, String(v));
  });
  return api.get(`/api/refunds?${search.toString()}`).then((res: any) => res.data);
};

type SearchProps = {
  status?: string;
  pageSize: number;
  page: number;
  customer_id?: string;
  currency_id?: string;
  invoice_id?: string;
  subscription_id?: string;
  payment_intent_id?: string;
  q?: Record<string, string>;
  o?: string;
};

type ListProps = {
  features?: {
    customer?: boolean;
    toolbar?: boolean;
    filter?: boolean;
    footer?: boolean;
  };
  customer_id?: string;
  invoice_id?: string;
  status?: string;
  subscription_id?: string;
  payment_intent_id?: string;
};

const getListKey = (props: ListProps) => {
  if (props.customer_id) {
    return `customer-refunds-${props.customer_id}`;
  }
  if (props.invoice_id) {
    return `invoice-refunds-${props.invoice_id}`;
  }
  if (props.subscription_id) {
    return `subscription-refunds-${props.subscription_id}`;
  }

  if (props.payment_intent_id) {
    return `payment-intent-refunds-${props.payment_intent_id}`;
  }

  return 'refunds';
};

export default function RefundList({
  customer_id = '',
  invoice_id = '',
  subscription_id = '',
  status = '',
  features = {
    customer: true,
    filter: true,
  },
  payment_intent_id = '',
}: ListProps) {
  const { t } = useLocaleContext();
  const [searchParams] = useSearchParams();

  const listKey = getListKey({ customer_id, invoice_id, subscription_id, payment_intent_id });
  const defaultPageSize = useDefaultPageSize(20);

  const [search, setSearch] = useCacheState<SearchProps>(listKey, {
    defaultValue: {
      status: status as string,
      customer_id,
      invoice_id,
      subscription_id,
      payment_intent_id,
      pageSize: defaultPageSize,
      page: 1,
    },
    getUrlParams: () => {
      const params: Record<string, any> = {};
      if (searchParams.has('status')) {
        params.status = searchParams.get('status');
      }
      if (searchParams.has('currency_id')) {
        params.currency_id = searchParams.get('currency_id');
      }
      if (searchParams.has('customer_id')) {
        params.customer_id = searchParams.get('customer_id');
      }
      return params;
    },
  });

  const [data, setData] = useState({}) as any;

  const refresh = () =>
    fetchData(search).then((res: any) => {
      setData(res);
    });

  useEffect(() => {
    refresh();
  }, [search]);

  if (!data.list) {
    return <CircularProgress />;
  }

  const columns = [
    {
      label: t('common.amount'),
      name: 'id',
      align: 'right',
      width: 80,
      options: {
        customBodyRenderLite: (_: string, index: number) => {
          const item = data.list[index] as TRefundExpanded;
          return (
            <Link to={`/admin/payments/${item.id}`}>
              <Typography
                component="strong"
                sx={{
                  fontWeight: 600,
                }}>
                {formatBNStr(item?.amount, item?.paymentCurrency.decimal)}&nbsp;
                {item?.paymentCurrency.symbol}
              </Typography>
            </Link>
          );
        },
      },
    },
    {
      label: t('common.paymentMethod'),
      name: 'paymentMethod',
      width: 120,
      options: {
        customBodyRenderLite: (_: string, index: number) => {
          const item = data.list[index] as TRefundExpanded;
          return (
            <Link to={`/admin/payments/${item.id}`}>
              <Typography sx={{ display: 'flex', alignItems: 'center', whiteSpace: 'nowrap' }}>
                <Avatar src={item.paymentMethod.logo} sx={{ width: 18, height: 18, mr: 1 }} />
                {item.paymentMethod.name}
              </Typography>
            </Link>
          );
        },
      },
    },
    {
      label: t('common.status'),
      name: 'status',
      width: 80,
      options: {
        filter: true,
        customBodyRenderLite: (_: string, index: number) => {
          const item = data.list[index] as TRefundExpanded;
          return (
            <Link to={`/admin/payments/${item.id}`}>
              <Status label={item.status} color={getPaymentIntentStatusColor(item.status)} />
            </Link>
          );
        },
      },
    },
    {
      label: t('common.type'),
      name: 'type',
      width: 80,
      options: {
        filter: true,
        customBodyRenderLite: (_: string, index: number) => {
          const item = data.list[index] as TRefundExpanded;
          return (
            <Link to={`/admin/payments/${item.id}`}>
              <Status label={t(`refund.type.${item.type}`)} />
            </Link>
          );
        },
      },
    },
    {
      label: t('common.description'),
      name: 'description',
      options: {
        customBodyRenderLite: (_: string, index: number) => {
          const item = data.list[index] as TRefundExpanded;
          return (
            <Link to={`/admin/payments/${item.id}`}>
              {item.description ? capitalize(toLower(item.description.replace(/_/g, ' '))) : item.id}
            </Link>
          );
        },
      },
    },
    {
      label: t('common.createdAt'),
      name: 'created_at',
      options: {
        sort: true,
        customBodyRenderLite: (_: string, index: number) => {
          const item = data.list[index] as TRefundExpanded;
          return <Link to={`/admin/payments/${item.id}`}>{formatTime(item.created_at)}</Link>;
        },
      },
    },
    {
      label: t('common.updatedAt'),
      name: 'updated_at',
      options: {
        sort: true,
        customBodyRenderLite: (_: string, index: number) => {
          const item = data.list[index] as TRefundExpanded;
          return <Link to={`/admin/payments/${item.id}`}>{formatTime(item.updated_at)}</Link>;
        },
      },
    },
    {
      label: t('common.actions'),
      name: '',
      options: {
        customBodyRenderLite: (_: string, index: number) => {
          const item = data.list[index] as TRefundExpanded;
          return <RefundActions data={item} onChange={() => refresh()} />;
        },
      },
    },
  ];

  if (features?.customer) {
    columns.splice(3, 0, {
      label: t('common.customer'),
      name: 'customer_id',
      options: {
        customBodyRenderLite: (_: string, index: number) => {
          const item = data.list[index] as TRefundExpanded;
          return <CustomerLink customer={item.customer} />;
        },
      },
    });
  }

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

  return (
    <Table
      hasRowLink
      data={data.list}
      durable={`__${listKey}__`}
      durableKeys={['searchText']}
      columns={columns}
      loading={!data.list}
      onChange={onTableChange}
      options={{
        count: data.count,
        page: search!.page - 1,
        rowsPerPage: search!.pageSize,
        onColumnSortChange(_: any, order: any) {
          setSearch({
            ...search!,
            q: search!.q || {},
            o: order,
          });
        },
        onSearchChange: (text: string) => {
          if (text) {
            setSearch({
              ...search!,
              q: {
                'like-description': text,
                'like-metadata': text,
              },
              pageSize: 100,
              page: 1,
            });
          } else {
            setSearch({
              ...search!,
              pageSize: 100,
              page: 1,
              q: {},
            });
          }
        },
      }}
      toolbar={features?.toolbar}
      footer={features?.footer}
      title={
        features?.filter && (
          <FilterToolbar
            setSearch={setSearch}
            search={search}
            status={['succeeded', 'canceled', 'failed', 'requires_action', 'pending']}
            currency
          />
        )
      }
      emptyNodeText={t('empty.refunds')}
    />
  );
}
