/* eslint-disable react/no-unstable-nested-components */
import { getDurableData } from '@arcblock/ux/lib/Datatable';
import { useLocaleContext } from '@arcblock/ux/lib/Locale/context';
import { Status, api, formatTime, usePaymentContext, Table, findCurrency, formatAmount } from '@blocklet/payment-react';
import { useEffect } from 'react';
import { Link } from 'react-router-dom';
import useBus from 'use-bus';

import { useLocalStorageState, useRequest } from 'ahooks';
import FilterToolbar from '../../../../components/filter-toolbar';

const fetchData = (params: Record<string, any> = {}): Promise<{ list: any[]; 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(' ');
    }
    if (key === 'status' && ['active', 'inactive'].includes(v)) {
      search.set('valid', v === 'active' ? 'true' : 'false');
      return;
    }
    search.set(key, String(v));
  });
  return api.get(`/api/coupons?${search.toString()}`).then((res: any) => res.data);
};

type SearchProps = {
  valid: string;
  pageSize: number;
  page: number;
  q?: any;
  o?: string;
};

export default function CouponsList() {
  const listKey = 'coupons';
  const persisted = getDurableData(listKey);

  const { t } = useLocaleContext();
  const { settings } = usePaymentContext();
  const [search, setSearch] = useLocalStorageState<SearchProps>(listKey, {
    defaultValue: {
      valid: '',
      pageSize: persisted.rowsPerPage || 20,
      page: persisted.page ? persisted.page + 1 : 1,
    },
  });

  const {
    data = {
      list: [],
      count: 0,
    },
    refresh,
  } = useRequest(() => fetchData(search), {
    refreshDeps: [search],
  });

  const couponList = data?.list || [];
  useBus('coupon.created', () => refresh(), []);
  useBus('coupon.updated', () => refresh(), []);
  useBus('coupon.deleted', () => refresh(), []);

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

  const formatCouponTerms = (coupon: any) => {
    let couponOff = '';
    if (coupon.percent_off && coupon.percent_off > 0) {
      couponOff = `${coupon.percent_off}%`;
    }
    if (coupon.amount_off && coupon.amount_off !== '0') {
      const currency = findCurrency(settings.paymentMethods, coupon.currency_id) || settings.baseCurrency;
      couponOff = `${formatAmount(coupon.amount_off, currency.decimal)} ${currency.symbol}`;
    }
    if (couponOff) {
      return t(`admin.coupon.couponTerms.${coupon.duration}`, { couponOff, months: coupon.duration_in_months });
    }
    return t('admin.coupon.noDiscount');
  };

  const columns = [
    {
      label: t('admin.coupon.listTitle'),
      name: 'name',
      options: {
        filter: true,
        customBodyRenderLite: (_: string, index: number) => {
          const item = couponList[index];
          return <Link to={`/admin/products/coupons/${item.id}`}>{item.name}</Link>;
        },
      },
    },
    {
      label: t('admin.coupon.terms'),
      name: 'terms',
      options: {
        filter: false,
        customBodyRenderLite: (_: string, index: number) => {
          const item = couponList[index];
          return <Link to={`/admin/products/coupons/${item.id}`}>{formatCouponTerms(item)}</Link>;
        },
      },
    },
    {
      label: t('admin.coupon.redemptions'),
      name: 'redemptions',
      options: {
        filter: false,
        customBodyRenderLite: (_: string, index: number) => {
          const item = couponList[index];
          const maxRedemptions = item.max_redemptions || t('admin.coupon.unlimited');
          const timesRedeemed = item.times_redeemed || 0;
          return (
            <Link to={`/admin/products/coupons/${item.id}`}>
              {timesRedeemed} / {maxRedemptions}
            </Link>
          );
        },
      },
    },
    {
      label: t('admin.coupon.expires'),
      name: 'expires',
      options: {
        filter: false,
        customBodyRenderLite: (_: string, index: number) => {
          const item = couponList[index];
          if (item.redeem_by) {
            return <Link to={`/admin/products/coupons/${item.id}`}>{formatTime(item.redeem_by * 1000)}</Link>;
          }
          return <Link to={`/admin/products/coupons/${item.id}`}>—</Link>;
        },
      },
    },
    {
      label: t('common.status'),
      name: 'valid',
      options: {
        filter: true,
        customBodyRenderLite: (_: string, index: number) => {
          const item = couponList[index];
          return (
            <Link to={`/admin/products/coupons/${item.id}`}>
              <Status
                label={item?.valid ? t('common.active') : t('common.inactive')}
                color={item?.valid ? 'success' : 'default'}
              />
            </Link>
          );
        },
      },
    },
  ];

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

  return (
    <Table
      hasRowLink
      durable={`__${listKey}__`}
      durableKeys={['page', 'rowsPerPage', 'searchText']}
      title={<FilterToolbar setSearch={setSearch} search={search} status={['active', 'inactive']} />}
      data={couponList}
      columns={columns}
      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-name': text,
                'like-id': text,
              },
              pageSize: 100,
              page: 1,
            });
          } else {
            setSearch({
              ...search!,
              pageSize: 100,
              page: 1,
              q: {},
            });
          }
        },
      }}
      loading={!couponList}
      onChange={onTableChange}
    />
  );
}
