/* eslint-disable react/no-unstable-nested-components */
import { getDurableData } from '@arcblock/ux/lib/Datatable';
import { useLocaleContext } from '@arcblock/ux/lib/Locale/context';
import { api, formatTime, getPrefix, Table, useDefaultPageSize } from '@blocklet/payment-react';
import type { TEventExpanded } from '@blocklet/payment-types';
import { Alert, Box, CircularProgress, Typography } from '@mui/material';
import { useRequest } from 'ahooks';
import { useEffect, useState } from 'react';

import { styled } from '@mui/system';
import { joinURL } from 'ufo';
import { useTransitionContext } from '../progress-bar';

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

type SearchProps = {
  pageSize: number;
  page: number;
  type?: string;
  object_id?: string;
};

type ListProps = {
  features?: {
    toolbar?: boolean;
  };
  type?: string;
  object_id?: string;
};

const getListKey = (props: ListProps) => {
  if (props.type) {
    return `events-${props.type}`;
  }
  if (props.object_id) {
    return `events-${props.object_id}`;
  }

  return 'events';
};

const getEventDescription = (event: TEventExpanded) => {
  switch (event.type) {
    case 'product.created':
      return `A new product ${event.object_id} was created`;
    case 'product.updated':
      return `The product with ID ${event.object_id} was updated`;
    case 'product.deleted':
      return `The product with ID ${event.object_id} was deleted`;
    case 'price.created':
      return `A new price ${event.object_id} was created`;
    case 'price.updated':
      return `The price with ID ${event.object_id} was updated`;
    case 'price.deleted':
      return `The price with ID ${event.object_id} was deleted`;
    case 'payment_link.created':
      return `A new payment link ${event.object_id} was created`;
    case 'payment_link.updated':
      return `The payment link with ID ${event.object_id} was updated`;
    case 'payment_link.deleted':
      return `The payment link with ID ${event.object_id} was deleted`;
    case 'payment_intent.created':
      return `A new payment intent ${event.object_id} was created`;
    case 'payment_intent.updated':
      return `The payment intent with ID ${event.object_id} was updated`;
    case 'payment_intent.canceled':
      return `The payment intent with ID ${event.object_id} was canceled`;
    case 'payment_intent.succeeded':
      return `The payment intent with ID ${event.object_id} succeeded`;
    case 'payment_intent.processing':
      return `The payment intent with ID ${event.object_id} is processing`;
    case 'payment_intent.requires_action':
      return `The payment intent with ID ${event.object_id} requires user action`;
    case 'payment_intent.payment_failed':
      return `The payment intent with ID ${event.object_id} failed to pay`;
    case 'payment_intent.deleted':
      return `The payment intent with ID ${event.object_id} was deleted`;
    case 'customer.created':
      return `A new customer ${event.object_id} was created`;
    case 'customer.updated':
      return `The customer with ID ${event.object_id} was updated`;
    case 'customer.deleted':
      return `The customer with ID ${event.object_id} was deleted`;
    case 'invoice.created':
      return `A new invoice ${event.object_id} was created`;
    case 'invoice.finalized':
      return `The invoice with ID ${event.object_id} was finalized`;
    case 'invoice.updated':
      return `The invoice with ID ${event.object_id} was updated`;
    case 'invoice.voided':
      return `The invoice with ID ${event.object_id} was marked as void`;
    case 'invoice.paid':
      return `The invoice with ID ${event.object_id} was marked as paid`;
    case 'invoice.marked_uncollectible':
      return `The invoice with ID ${event.object_id} was marked as uncollectible`;
    case 'invoice.deleted':
      return `The invoice with ID ${event.object_id} was deleted`;
    case 'checkout.session.completed':
      return `The checkout session ${event.object_id} completed`;
    case 'checkout.session.expired':
      return `The checkout session ${event.object_id} expired`;
    case 'customer.subscription.created':
      return `A new subscription ${event.object_id} was created`;
    case 'customer.subscription.updated':
      return `The subscription with ID ${event.object_id} was updated`;
    case 'customer.subscription.resumed':
      return `The subscription with ID ${event.object_id} was resumed`;
    case 'customer.subscription.paused':
      return `The subscription with ID ${event.object_id} was paused`;
    case 'customer.subscription.deleted':
      return `The subscription with ID ${event.object_id} was canceled`;
    default:
      return `${event.type}: ${event.object_id}`;
  }
};

export default function EventList({ type = '', object_id = '', features = { toolbar: true } }: ListProps) {
  const listKey = getListKey({ type, object_id });
  const persisted = getDurableData(listKey);

  const { t } = useLocaleContext();
  const defaultPageSize = useDefaultPageSize(persisted.rowsPerPage || 50);
  const [search, setSearch] = useState<SearchProps>({
    type,
    object_id,
    pageSize: defaultPageSize,
    page: persisted.page ? persisted.page + 1 : 1,
  });
  const { startTransition } = useTransitionContext();

  const { loading, error, data, refresh } = useRequest(() => fetchData(search));
  useEffect(() => {
    refresh();
  }, [search, refresh]);

  if (error) {
    return <Alert severity="error">{error.message}</Alert>;
  }

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

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

  const columns = [
    {
      label: t('common.description'),
      name: 'type',
      options: {
        customBodyRenderLite: (_: string, index: number) => {
          const item = data.list[index] as TEventExpanded;
          return getEventDescription(item);
        },
      },
    },
    {
      label: t('common.id'),
      name: 'id',
    },
    {
      label: t('common.createdAt'),
      name: 'created_at',
      minWidth: 100,
      options: {
        customBodyRender: (e: string) => {
          return formatTime(e);
        },
      },
    },
  ].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 (
    <Root>
      <Table
        hasRowLink
        durable={listKey}
        durableKeys={['page', 'rowsPerPage']}
        data={data.list}
        columns={columns}
        loading={loading}
        onChange={onTableChange}
        options={{
          count: data.count,
          page: search.page - 1,
          rowsPerPage: search.pageSize,
          onRowClick: (_: any, { dataIndex }: any) => {
            const item = data.list[dataIndex] as TEventExpanded;
            startTransition(() => {
              window.open(joinURL(getPrefix(), `/admin/developers/${item.id}`), '_blank');
            });
          },
        }}
        toolbar={features?.toolbar}
        emptyNodeText={t('empty.events')}
      />
    </Root>
  );
}

const Root = styled(Box)`
  td {
    cursor: pointer;
  }
`;
