/* eslint-disable react/no-unstable-nested-components */
import { useLocaleContext } from '@arcblock/ux/lib/Locale/context';
import DID from '@arcblock/ux/lib/DID';
import {
  Status,
  api,
  formatBNStr,
  formatError,
  formatPrettyMsLocale,
  formatSubscriptionProduct,
  formatTime,
  formatToDate,
  formatToDatetime,
  getCustomerAvatar,
  getDidConnectQueryParams,
  getInvoiceDescriptionAndReason,
  getInvoiceStatusColor,
  getPrefix,
  useDefaultPageSize,
  useMobile,
  OverdueInvoicePayment,
  PaymentProvider,
} from '@blocklet/payment-react';
import type { Paginated, TInvoiceExpanded, TSubscriptionExpanded } from '@blocklet/payment-types';
import {
  Alert,
  Box,
  Button,
  CircularProgress,
  Link,
  List,
  ListItem,
  ListSubheader,
  Stack,
  Tooltip,
  Typography,
  useTheme,
} from '@mui/material';
import { useRequest, useSetState } from 'ahooks';
import SplitButton from '@arcblock/ux/lib/SplitButton';
import { useMemo } from 'react';
import { joinURL, withQuery } from 'ufo';
import prettyMs from 'pretty-ms-i18n';
import { isEmpty } from 'lodash';
import InfoRow from '../../../components/info-row';
import InfoCard from '../../../components/info-card';
import { useSessionContext } from '../../../contexts/session';
import SubscriptionStatus from '../../../components/subscription/status';

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

const fetchSubscriptionData = (id: string, authToken: string): Promise<TSubscriptionExpanded> => {
  if (!id) {
    throw new Error('Subscription ID is missing');
  }

  return api.get(`/api/subscriptions/${id}?authToken=${authToken}`).then((res: any) => res.data);
};

const checkHasPastDue = async (subscriptionId: string, authToken: string): Promise<boolean> => {
  try {
    const res = await api.get(`/api/subscriptions/${subscriptionId}/summary?authToken=${authToken}`);
    if (!isEmpty(res.data) && Object.keys(res.data).length >= 1) {
      return true;
    }
    return false;
  } catch (error) {
    console.error('Failed to check past due:', error);
    return false;
  }
};

export default function SubscriptionEmbed() {
  const { t, locale } = useLocaleContext();
  const params = new URL(window.location.href).searchParams;
  const [state, setState] = useSetState({
    batchPay: false,
  });
  const { session, connectApi } = useSessionContext();

  const subscriptionId = params.get('id') || '';
  const authToken = params.get('authToken') || '';
  const defaultPageSize = useDefaultPageSize(20);
  const { isMobile } = useMobile();
  const {
    data: subscription,
    error,
    loading,
    runAsync: refreshSubscription,
  } = useRequest(() => fetchSubscriptionData(subscriptionId, authToken));
  const { data, runAsync: refreshInvoices } = useRequest(
    () =>
      fetchInvoiceData({
        page: 1,
        pageSize: defaultPageSize,
        status: 'open,paid,uncollectible',
        subscription_id: subscriptionId,
        authToken,
        ignore_zero: true,
        include_staking: true,
        customer_id: subscription?.customer_id,
        include_overdraft_protection: false,
      }),
    {
      refreshDeps: [subscriptionId, authToken, subscription?.customer_id],
    }
  );
  const muiTheme = useTheme();

  const subscriptionPageUrl: string = useMemo(() => {
    if (!subscription) {
      return '#';
    }

    const pageUrl: string = joinURL(getPrefix(), `/customer/subscription/${subscription.id}`);

    return withQuery(pageUrl, {
      source: 'embed',
      ...getDidConnectQueryParams({ forceConnected: subscription.customer.did }),
    });
  }, [subscription]);

  const { data: hasPastDue, runAsync: runCheckHasPastDue } = useRequest(
    () => checkHasPastDue(subscriptionId, authToken),
    {
      refreshDeps: [subscriptionId, authToken],
    }
  );

  if (error) {
    return (
      <Position>
        <Alert severity="error">{formatError(error)}</Alert>
      </Position>
    );
  }
  if (!subscription || loading) {
    return (
      <Position>
        <CircularProgress />
      </Position>
    );
  }

  const invoices = data?.list || [];

  const infoList: { name: string; value: React.ReactNode }[] = [
    {
      name: t('payment.customer.subscriptions.plan'),
      value: (
        <Typography
          sx={{
            fontWeight: 600,
            marginRight: '10px',
          }}>
          {formatSubscriptionProduct(subscription.items)}
        </Typography>
      ),
    },
    {
      name: t('common.status'),
      value: <SubscriptionStatus subscription={subscription} />,
    },
  ];

  if (subscription.status === 'trialing') {
    const endTimestamp = subscription.current_period_end * 1000;
    const remainingTime = endTimestamp - Date.now();

    infoList.push({
      name: t('payment.customer.subscriptions.trialLeft'),
      value: (
        <Typography
          sx={{
            color: 'success.main',
            fontWeight: 'bold',
            marginRight: '10px',
          }}>
          <Tooltip title={formatToDatetime(endTimestamp, locale)} placement="top-end" enterTouchDelay={0}>
            <Typography component="span" sx={{ cursor: 'pointer' }}>
              {prettyMs(remainingTime, {
                locale: formatPrettyMsLocale(locale),
                compact: false,
                verbose: true,
                unitCount: 2,
              })}
            </Typography>
          </Tooltip>
        </Typography>
      ),
    });
  }

  if (subscription.status === 'active') {
    infoList.push({
      name: t('payment.customer.subscriptions.nextInvoice'),
      value: (
        <Typography
          sx={{
            color: 'success.main',
            fontWeight: 'bold',
            marginRight: '10px',
          }}>
          {formatTime(subscription.current_period_end * 1000)}
        </Typography>
      ),
    });

    infoList.push({
      name: t('payment.customer.subscriptions.owner'),
      value: (
        <InfoCard
          logo={getCustomerAvatar(
            subscription.customer.did,
            subscription.customer.updated_at ? new Date(subscription.customer.updated_at).toISOString() : '',
            24
          )}
          description=""
          className="owner-info-card"
          name={subscription.customer.name || subscription.customer.email}
          tooltip={
            <Stack>
              <Typography>
                {subscription.customer.name} ({subscription.customer.email})
              </Typography>
              <DID did={subscription.customer.did} />
            </Stack>
          }
          size={24}
          variant="circular"
        />
      ),
    });
  }

  return (
    <Position>
      <PaymentProvider session={session} connect={connectApi}>
        <Box
          className="mini-invoice-wrap"
          sx={{
            display: 'flex',
            flexDirection: 'column',
            alignItem: 'center',
            justifyContent: 'flex-start',
            padding: '8px',
            gap: '12px',
            width: '100%',
            height: '100%',
          }}>
          <Typography component="h2" sx={{ textAlign: 'center' }} variant="h3" gutterBottom>
            {t('payment.customer.subscriptions.current')}
          </Typography>
          <Box sx={{ display: 'flex', flexDirection: 'column' }}>
            {infoList.map(({ name, value }) => {
              return (
                <InfoRow
                  label={name}
                  value={value}
                  sx={{
                    mb: 0,
                    py: 1.5,
                    borderBottom: `1px solid ${muiTheme.palette.divider}`,
                    '.info-row-label': {
                      whiteSpace: 'nowrap',
                    },
                    '.info-row-value': {
                      flex: 'none',
                    },
                    '.owner-info-card .info-card': {
                      minWidth: 0,
                    },
                  }}
                />
              );
            })}
          </Box>
          <Box sx={{ flex: 1, overflow: 'hidden' }}>
            <List sx={{ height: '100%', display: 'flex', flexDirection: 'column' }} className="mini-invoice-list">
              <ListSubheader disableGutters sx={{ padding: 0 }}>
                <Typography
                  component="h2"
                  variant="h6"
                  sx={{
                    fontSize: 14,
                    color: 'text.primary',
                  }}>
                  {t('payment.customer.invoices')}
                </Typography>
              </ListSubheader>
              {(invoices as any).length === 0 ? (
                <Typography
                  sx={{
                    color: 'text.lighter',
                  }}>
                  {t('payment.customer.invoice.empty')}
                </Typography>
              ) : (
                <Box sx={{ flex: 1, overflow: 'auto' }}>
                  {(invoices as any).map((item: any) => {
                    return (
                      <ListItem key={item.id} disableGutters sx={{ display: 'flex', justifyContent: 'space-between' }}>
                        <Typography component="div" sx={{ flex: 3, gap: 1, display: 'flex', alignItems: 'center' }}>
                          <Typography component="span" sx={{ whiteSpace: 'nowrap' }}>
                            {formatToDate(item.created_at, locale, 'YYYY-MM-DD')}
                          </Typography>
                          {!isMobile && <Status label={getInvoiceDescriptionAndReason(item, locale)?.type} />}
                        </Typography>
                        <Typography component="span" sx={{ flex: 1, textAlign: 'right' }}>
                          {formatBNStr(item.total, item.paymentCurrency.decimal)}&nbsp;
                          {item.paymentCurrency.symbol}
                        </Typography>
                        <Typography component="span" sx={{ flex: 2, textAlign: 'right' }}>
                          <Status label={item.status} color={getInvoiceStatusColor(item.status)} />
                        </Typography>
                      </ListItem>
                    );
                  })}
                </Box>
              )}
            </List>
          </Box>
          <Stack
            direction="row"
            spacing={2}
            sx={{
              justifyContent: 'center',
              mt: 2,
              width: '100%',
            }}>
            {subscription.service_actions
              ?.filter((x: any) => x?.type !== 'notification')
              ?.map((x: any) => (
                // @ts-ignore
                <Button
                  component={Link}
                  key={x.name}
                  variant={x?.variant || 'contained'}
                  color={x.color || 'primary'}
                  href={x.link}
                  size="small"
                  target="_blank"
                  sx={{
                    textDecoration: 'none !important',
                    flex: 1,
                    minWidth: 0,
                  }}>
                  {x.text[locale] || x.text.en || x.name}
                </Button>
              ))}
            {hasPastDue ? (
              <SplitButton
                size="small"
                color="error"
                variant="contained"
                sx={{
                  flex: 1,
                  minWidth: 0,
                }}
                menu={[
                  <SplitButton.Item key="view-subscription" component={Link} target="_blank" href={subscriptionPageUrl}>
                    {t('payment.customer.subscriptions.view')}
                  </SplitButton.Item>,
                ]}>
                {() => (
                  <Button variant="contained" color="error" onClick={() => setState({ batchPay: true })}>
                    {t('payment.subscription.overdue.payNow')}
                  </Button>
                )}
              </SplitButton>
            ) : (
              <Button
                variant="contained"
                sx={{
                  flex: 1,
                  minWidth: 0,
                }}
                target="_blank"
                href={subscriptionPageUrl}>
                {t('payment.customer.subscriptions.view')}
              </Button>
            )}
          </Stack>
        </Box>
        {state.batchPay && (
          <OverdueInvoicePayment
            subscriptionId={subscriptionId}
            onPaid={() => {
              setState({
                batchPay: false,
              });
              refreshSubscription();
              runCheckHasPastDue();
              refreshInvoices();
            }}
            dialogProps={{
              open: state.batchPay,
              onClose: () => setState({ batchPay: false }),
            }}
            authToken={authToken}
          />
        )}
      </PaymentProvider>
    </Position>
  );
}

function Position({ children }: any) {
  return (
    <Box
      className="mini-invoice-box" // 预留 class 用于设置定位
      sx={{
        padding: '8px',
        width: '100%',
        maxWidth: '500px',
        backgroundColor: 'background.paper',
        margin: '0 auto',
        height: '100vh',
      }}>
      {children}
    </Box>
  );
}
